java日志篇(4)-common-logging

慢慢來比較快队萤,虛心學技術

前言:Jakarta Commons-logging(JCL)是apache最早提供的日志的門面接口匿醒。它將一些具體的日志組件抽象為接口介评,實現(xiàn)日志操作的解耦和可插拔,讓眾多的日志工具有一個共同的操作方式

一、common-logging簡單使用示例

①引入common-logging的jar包窜骄,最新jar包從官方網(wǎng)站http://commons.apache.org/proper/commons-logging/download_logging.cgi進行下載,下載后將jar包放到lib中引入項目即可摆屯。

如果是maven項目在pom文件中添加依賴如下:

<!--引入common-logging-->
<dependency>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
   <version>1.2</version>
</dependency>

②創(chuàng)建common-logging.properties文件,將其放在classpath下邻遏,如果是maven項目則將其放在src/main/resource目錄下,配置內(nèi)容如下

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

③在項目程序中使用logger開發(fā)

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class CommonsTest {

    //獲取logger
    private final static Log logger = LogFactory.getLog(CommonsTest.class);

    public static void main(String[] args) {
        //使用logger輸出日志
        logger.trace("TRACE...");
        logger.debug("DEBUG ...");
        logger.info("INFO ...");
        logger.error("ERROR ...");
        logger.warn("WARN...");
    }
}

運行輸出結(jié)果:

[INFO] CommonsTest - INFO ...
[ERROR] CommonsTest - ERROR ...
[WARN] CommonsTest - WARN...

如上實現(xiàn)第一個簡單的common-logging程序虐骑,引發(fā)以下幾個問題

問題一:common-logging.properties屬性文件中的org.apache.commons.logging.Log和它的值代表了什么准验?

問題二:為什么明明代碼中寫了logger.trace和logger.debug,卻沒有輸出廷没?

問題三:LogFactory的實現(xiàn)原理是什么糊饱?

帶著問題去思考學習,效率總是最高的

二颠黎、問題探索

1.org.apache.commons.logging.Log

JCL有兩個基本的抽象類: Log( 基本記錄器 ) 和 LogFactory( 負責創(chuàng)建 Log 實例 )另锋,其中滞项,Log有多個默認實現(xiàn)類,分別是:

-org.apache.commons.logging.impl.Jdk14Logger 使用JUL砰蠢。
-org.apache.commons.logging.impl.Log4JLogger 使用Log4J蓖扑。
-org.apache.commons.logging.impl.LogKitLogger 使用 avalon-Logkit唉铜。
-org.apache.commons.logging.impl.SimpleLog common-logging自帶日志實現(xiàn)類台舱。它實現(xiàn)了Log接口,把日志消息都輸出到系統(tǒng)錯誤流System.err 中潭流。
-org.apache.commons.logging.impl.NoOpLog common-logging自帶日志實現(xiàn)類竞惋。它實現(xiàn)了Log接口。 其輸出日志的方法中不進行任何操作灰嫉。

在common-logging.properties中配置的org.apache.commons.logging.Log參數(shù)指定了common-logging將使用哪種日志實現(xiàn)拆宛,這也是前言所說的,通過配置實現(xiàn)日志組件的可插拔和解耦讼撒,極大增加了靈活性

2.common-logging日志級別

common-logging日志級別從高到低如下:

1)fatal 非常嚴重的錯誤浑厚,導致系統(tǒng)中止。期望這類信息能立即顯示在狀態(tài)控制臺上根盒。

2)error 其它運行期錯誤或不是預期的條件钳幅。期望這類信息能立即顯示在狀態(tài)控制臺上。

3)warn 使用了不贊成使用的API炎滞、非常拙劣使用API, '幾乎就是'錯誤, 其它運行時不合需要和不合預期的狀態(tài)但還沒必要稱為 "錯誤"敢艰。期望這類信息能立即顯示在狀態(tài)控制臺上。

4)info 運行時產(chǎn)生的有意義的事件册赛。期望這類信息能立即顯示在狀態(tài)控制臺上钠导。

5)debug 系統(tǒng)流程中的細節(jié)信息。期望這類信息僅被寫入log文件中森瘪。

6)trace 更加細節(jié)的信息牡属。期望這類信息僅被寫入log文件中。

apache建議使用4級扼睬,即 ERROR逮栅、WARNINFO痰驱、DEBUG

而當我們在common-logging.properties配置使用的是SimpleLog日志實現(xiàn)证芭,該日志實現(xiàn)默認日志級別是info,所以才會出現(xiàn)簡單實例中的輸出結(jié)果担映,如何更改SimpleLog的日志級別废士?

創(chuàng)建simplelog.properties配置文件,放到classpath下蝇完,如果是maven則放到src/main/resource目錄下,配置內(nèi)容參考:

org.apache.commons.logging.simplelog.defaultlog=TRACE

配置后結(jié)果輸出如下(bingo):

[TRACE] CommonsTest - TRACE...
[DEBUG] CommonsTest - DEBUG ...
[INFO] CommonsTest - INFO ...
[ERROR] CommonsTest - ERROR ...
[WARN] CommonsTest - WARN...

3.LogFactory實現(xiàn)原理

LogFactory作為log的工廠存在官硝,使用動態(tài)查找機制進行l(wèi)og實例的獲取矗蕊,具體執(zhí)行步驟如下:

①首先在classpath下尋找commons-logging.properties文件。如果找到氢架,則使用其中定義的Log實現(xiàn)類傻咖;如果找不到,則在查找是否已定義系統(tǒng)環(huán)境變量org.apache.commons.logging.Log岖研,找到則使用其定義的Log實現(xiàn)類卿操;

②查看classpath中是否有Log4j的包,如果發(fā)現(xiàn)孙援,則自動使用Log4j作為日志實現(xiàn)類害淤;

③使用JDK自身的日志實現(xiàn)類(JDK1.4以后才有日志實現(xiàn)類);

④使用commons-logging自己提供的一個簡單的日志實現(xiàn)類SimpleLog拓售;

上述步驟當LogFactory成功找到一個日志實現(xiàn)之后就會停止

實際上窥摄,看源碼發(fā)現(xiàn),LogFactory的核心步驟在于discoverLogImplementation方法础淤,源碼分析如下:

 if (isDiagnosticsEnabled()) {
            this.logDiagnostic("Discovering a Log implementation...");
        }

        this.initConfiguration();
        Log result = null;
        //從common-logging.properties文件中提取org.apache.commons.logging.Log這個變量的value
        String specifiedLogClassName = this.findUserSpecifiedLogClassName();

        //配置文件中存在該變量則實例化
        if (specifiedLogClassName != null) {
            if (isDiagnosticsEnabled()) {
                this.logDiagnostic("Attempting to load user-specified log class '" + specifiedLogClassName + "'...");
            }

            //核驗相應日志對象是否存在
            result = this.createLogFromClass(specifiedLogClassName, logCategory, true);

            //如果日志對象不存在崭放,則報錯
            if (result == null) {
                StringBuffer messageBuffer = new StringBuffer("User-specified log class '");
                messageBuffer.append(specifiedLogClassName);
                messageBuffer.append("' cannot be found or is not useable.");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Log4JLogger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk14Logger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk13LumberjackLogger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.SimpleLog");
                throw new LogConfigurationException(messageBuffer.toString());
            } else {
                return result;
            }
        } else {
            //當日志文件中不存在該變量時,按照機制遍歷classesToDiscover字符串數(shù)組

            if (isDiagnosticsEnabled()) {
                this.logDiagnostic("No user-specified Log implementation; performing discovery using the standard supported logging implementations...");
            }

            //遍歷classesToDiscover字符串數(shù)組獲取日志實例(動態(tài)查找機制)
            for(int i = 0; i < classesToDiscover.length && result == null; ++i) {
                result = this.createLogFromClass(classesToDiscover[i], logCategory, true);
            }

            //到最后仍舊找不到匹配的日志實例鸽凶,則拋錯
            if (result == null) {
                throw new LogConfigurationException("No suitable Log implementation");
            } else {
                return result;
            }
        }

三币砂、進階,common-logging+log4j應用

log4j功能強大吱瘩,為了解耦和減少依賴道伟,大部分的項目都會使用common-logging+log4j的組合進行開發(fā),使用起來也是十分的簡單:

①引入log4j的jar包使碾,最新jar包從官方網(wǎng)站http://logging.apache.org/log4j/1.2/download.html進行下載蜜徽,下載后將jar包放到lib中引入項目即可。

如果是maven項目在pom文件中添加依賴如下:

<dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
</dependency>

②在common-logging.properties文件,將log指向log4j

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

③創(chuàng)建log4j.properties文件票摇,并將文件放在classpath下拘鞋,如果是maven則放在source/main/resource目錄下,簡單配置如下:

#配置rootLogger
log4j.rootLogger=all,appender1

#配置第一個appender
log4j.appender.appender1=org.apache.log4j.FileAppender
#配置文件輸出樣式
log4j.appender.appender1.layout = org.apache.log4j.PatternLayout
log4j.appender.appender1.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
#指定僅記錄ERROR以上級別的日志
log4j.appender.appender1.Threshold = ERROR
log4j.appender.appender1.ImmediateFlush = TRUE
#指定將日志累加到日志文件末尾
log4j.appender.appender1.Append = TRUE
#指定日志文件
log4j.appender.appender1.File = ./Common-logging-Modle/log/error.log
log4j.appender.appender1.Encoding = UTF-8

④運行代碼不變矢门,結(jié)果如下:

error.log

[ERROR][2019/01/31 17:56:13569][com.log.CommonsTest.main(CommonsTest.java:16)]
ERROR ...

總結(jié)

1.盡可能將可配置的內(nèi)容抽離作為配置盆色,而不是在代碼中做更改,可以極大增強系統(tǒng)靈活性

2.common-logging的日志級別分為六個祟剔,默認級別為info隔躲,apache推薦使用四個級別:ERRORWARN物延、INFO宣旱、DEBUG

3.common-logging的關鍵類log有5個基本實現(xiàn)類,分別是org.apache.commons.logging.impl.Jdk14Logger叛薯,org.apache.commons.logging.impl.Log4JLogger浑吟,org.apache.commons.logging.impl.LogKitLogger笙纤,org.apache.commons.logging.impl.SimpleLog,org.apache.commons.logging.impl.NoOpLog

4.LogFactory使用動態(tài)查找機制進行日志實例化组力,執(zhí)行順序為:common-logging.properties---->系統(tǒng)環(huán)境變量------->log4j--->jul--->simplelog---->nooplog

參考文檔:

【1】官方文檔

【2】https://blog.csdn.net/backbug/article/details/78655664

【3】http://www.reibang.com/p/b818d9d26d39

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末省容,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子燎字,更是在濱河造成了極大的恐慌腥椒,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轩触,死亡現(xiàn)場離奇詭異寞酿,居然都是意外死亡家夺,警方通過查閱死者的電腦和手機脱柱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拉馋,“玉大人榨为,你說我怎么就攤上這事』蛙睿” “怎么了随闺?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔓腐。 經(jīng)常有香客問我矩乐,道長,這世上最難降的妖魔是什么回论? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任散罕,我火速辦了婚禮,結(jié)果婚禮上傀蓉,老公的妹妹穿的比我還像新娘欧漱。我一直安慰自己,他們只是感情好葬燎,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布误甚。 她就那樣靜靜地躺著,像睡著了一般谱净。 火紅的嫁衣襯著肌膚如雪窑邦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天壕探,我揣著相機與錄音冈钦,去河邊找鬼。 笑死浩蓉,一個胖子當著我的面吹牛派继,可吹牛的內(nèi)容都是我干的宾袜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼驾窟,長吁一口氣:“原來是場噩夢啊……” “哼庆猫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绅络,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤月培,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后恩急,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杉畜,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年衷恭,在試婚紗的時候發(fā)現(xiàn)自己被綠了此叠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡随珠,死狀恐怖灭袁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窗看,我是刑警寧澤茸歧,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布软瞎,位于F島的核電站,受9級特大地震影響拉讯,放射性物質(zhì)發(fā)生泄漏涤浇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一遂唧、第九天 我趴在偏房一處隱蔽的房頂上張望芙代。 院中可真熱鬧,春花似錦盖彭、人聲如沸纹烹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铺呵。三九已至,卻和暖如春隧熙,著一層夾襖步出監(jiān)牢的瞬間片挂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留音念,地道東北人沪饺。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像闷愤,于是被迫代替她去往敵國和親整葡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容