使用Commons Logging與Log4j

使用Commons Logging

和Java標準庫提供的日志不同赤屋,Commons Logging是一個第三方日志庫罢缸,它是由Apache創(chuàng)建的日志模塊。

Commons Logging的特色是,它可以掛接不同的日志系統(tǒng)蹈垢,并通過配置文件指定掛接的日志系統(tǒng)。默認情況下袖裕,Commons Loggin自動搜索并使用Log4j(Log4j是另一個流行的日志系統(tǒng))曹抬,如果沒有找到Log4j,再使用JDK Logging急鳄。

使用Commons Logging只需要和兩個類打交道谤民,并且只有兩步:

  • 第一步,通過LogFactory獲取Log類的實例疾宏;
  • 第二步张足,使用Log實例的方法打日志。
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Main {
    public static void main(String[] args) {
        Log log = LogFactory.getLog(Main.class);
        log.info("start...");
        log.warn("end.");
    }
}

運行上述代碼灾锯,肯定會得到編譯錯誤兢榨,類似error: package org.apache.commons.logging does not exist(找不到org.apache.commons.logging這個包)。因為Commons Logging是一個第三方提供的庫顺饮,所以吵聪,必須先把它下載下來。下載后兼雄,解壓吟逝,找到commons-logging-1.2.jar這個文件,再把Java源碼Main.java放到一個目錄下赦肋,例如work目錄:

然后用javac編譯Main.java块攒,編譯的時候要指定classpath励稳,不然編譯器找不到我們引用的org.apache.commons.logging包。編譯命令如下:

javac -cp commons-logging-1.2.jar Main.java

如果編譯成功囱井,那么當前目錄下就會多出一個Main.class文件:

現(xiàn)在可以執(zhí)行這個Main.class驹尼,使用java命令,也必須指定classpath庞呕,命令如下:

java -cp .;commons-logging-1.2.jar Main

注意到傳入的classpath有兩部分:一個是.新翎,一個是commons-logging-1.2.jar,用;分割住练。.表示當前目錄地啰,如果沒有這個.,JVM不會在當前目錄搜索Main.class讲逛,就會報錯亏吝。

如果在Linux或macOS下運行,注意classpath的分隔符不是;盏混,而是:

java -cp .:commons-logging-1.2.jar Main

運行結(jié)果如下:

//Mar 02, 2019 7:15:31 PM Main main
//INFO: start...
//Mar 02, 2019 7:15:31 PM Main main
//WARNING: end.

Commons Logging定義了6個日志級別:

  1. FATAL
  2. ERROR
  3. WARNING
  4. INFO
  5. DEBUG
  6. TRACE

默認級別是INFO蔚鸥。使用Commons Logging時,如果在靜態(tài)方法中引用Log许赃,通常直接定義一個靜態(tài)類型變量:

// 在靜態(tài)方法中引用Log:
public class Main {
    static final Log log = LogFactory.getLog(Main.class);

    static void foo() {
        log.info("foo");
    }
}

在實例方法中引用Log株茶,通常定義一個實例變量:

// 在實例方法中引用Log:
public class Person {
    protected final Log log = LogFactory.getLog(getClass());

    void foo() {
        log.info("foo");
    }
}

注意到實例變量log的獲取方式是LogFactory.getLog(getClass()),雖然也可以用LogFactory.getLog(Person.class)图焰,但是前一種方式有個非常大的好處,就是子類可以直接使用該log實例蹦掐。例如:

// 在子類中使用父類實例化的log:
public class Student extends Person {
    void bar() {
        log.info("bar");
    }
}

由于Java類的動態(tài)特性技羔,子類獲取的log字段實際上相當于LogFactory.getLog(Student.class),但卻是從父類繼承而來卧抗,并且無需改動代碼藤滥。

此外,Commons Logging的日志方法社裆,例如info()拙绊,除了標準的info(String)外,還提供了一個非常有用的重載方法:info(String, Throwable)泳秀,這使得記錄異常更加簡單:

try {
    ...
} catch (Exception e) {
    log.error("got exception!", e);
}

小結(jié)

  • Commons Logging是使用最廣泛的日志模塊标沪;
  • Commons Logging的API非常簡單;
  • Commons Logging可以自動檢測并使用其他日志模塊嗜傅。

使用Log4j

前面介紹了Commons Logging金句,可以作為“日志接口”來使用。而真正的“日志實現(xiàn)”可以使用Log4j吕嘀。Log4j是一種非常流行的日志框架违寞,最新版本是2.x贞瞒。

Log4j是一個組件化設(shè)計的日志系統(tǒng),它的架構(gòu)大致如下:

當我們使用Log4j輸出一條日志時趁曼,Log4j自動通過不同的Appender把同一條日志輸出到不同的目的地军浆。例如:

  • console:輸出到屏幕;
  • file:輸出到文件挡闰;
  • socket:通過網(wǎng)絡輸出到遠程計算機乒融;
  • jdbc:輸出到數(shù)據(jù)庫

在輸出日志的過程中,通過Filter來過濾哪些log需要被輸出尿这,哪些log不需要被輸出簇抵。例如,僅輸出ERROR級別的日志射众。
上述結(jié)構(gòu)雖然復雜碟摆,但我們在實際使用的時候,并不需要關(guān)心Log4j的API叨橱,而是通過配置文件來配置它典蜕。

以XML配置為例,使用Log4j的時候罗洗,我們把一個log4j2.xml的文件放到classpath下就可以讓Log4j讀取配置文件并按照我們的配置來輸出日志愉舔。下面是一個配置文件的例子:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Properties>
        <!-- 定義日志格式 -->
        <Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}%n%msg%n%n</Property>
        <!-- 定義文件名變量 -->
        <Property name="file.err.filename">log/err.log</Property>
        <Property name="file.err.pattern">log/err.%i.log.gz</Property>
    </Properties>
    <!-- 定義Appender,即目的地 -->
    <Appenders>
        <!-- 定義輸出到屏幕 -->
        <Console name="console" target="SYSTEM_OUT">
            <!-- 日志格式引用上面定義的log.pattern -->
            <PatternLayout pattern="${log.pattern}" />
        </Console>
        <!-- 定義輸出到文件,文件名引用上面定義的file.err.filename -->
        <RollingFile name="err" bufferedIO="true" fileName="${file.err.filename}" filePattern="${file.err.pattern}">
            <PatternLayout pattern="${log.pattern}" />
            <Policies>
                <!-- 根據(jù)文件大小自動切割日志 -->
                <SizeBasedTriggeringPolicy size="1 MB" />
            </Policies>
            <!-- 保留最近10份 -->
            <DefaultRolloverStrategy max="10" />
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <!-- 對info級別的日志伙菜,輸出到console -->
            <AppenderRef ref="console" level="info" />
            <!-- 對error級別的日志轩缤,輸出到err,即上面定義的RollingFile -->
            <AppenderRef ref="err" level="error" />
        </Root>
    </Loggers>
</Configuration>

雖然配置Log4j比較繁瑣贩绕,但一旦配置完成火的,使用起來就非常方便。對上面的配置文件淑倾,凡是INFO級別的日志馏鹤,會自動輸出到屏幕,而ERROR級別的日志娇哆,不但會輸出到屏幕湃累,還會同時輸出到文件。并且碍讨,一旦日志文件達到指定大兄瘟Α(1MB),Log4j就會自動切割新的日志文件勃黍,并最多保留10份琴许。

有了配置文件還不夠,因為Log4j也是一個第三方庫溉躲,我們需要從這里下載Log4j榜田,解壓后益兄,把以下3個jar包放到classpath中:

  • log4j-api-2.x.jar
  • log4j-core-2.x.jar
  • log4j-jcl-2.x.jar

因為Commons Logging會自動發(fā)現(xiàn)并使用Log4j,所以箭券,把上一節(jié)下載的commons-logging-1.2.jar也放到classpath中净捅。

要打印日志,只需要按Commons Logging的寫法寫辩块,不需要改動任何代碼蛔六,就可以得到Log4j的日志輸出,類似:

03-03 12:09:45.880 [main] INFO  com.itranswarp.learnjava.Main
Start process...

最佳實踐

在開發(fā)階段废亭,始終使用Commons Logging接口來寫入日志国章,并且開發(fā)階段無需引入Log4j。如果需要把日志寫入文件豆村, 只需要把正確的配置文件和Log4j相關(guān)的jar包放入classpath液兽,就可以自動把日志切換成使用Log4j寫入,無需修改任何代碼掌动。

小結(jié)

  • 通過Commons Logging實現(xiàn)日志四啰,不需要修改代碼即可使用Log4j;
  • 使用Log4j只需要把log4j2.xml和相關(guān)jar放入classpath粗恢;
  • 如果要更換Log4j柑晒,只需要移除log4j2.xml和相關(guān)jar;
  • 只有擴展Log4j時眷射,才需要引用Log4j的接口(例如匙赞,將日志加密寫入數(shù)據(jù)庫的功能,需要自己開發(fā))妖碉。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罚屋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嗅绸,更是在濱河造成了極大的恐慌,老刑警劉巖撕彤,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鱼鸠,死亡現(xiàn)場離奇詭異,居然都是意外死亡羹铅,警方通過查閱死者的電腦和手機蚀狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來职员,“玉大人麻蹋,你說我怎么就攤上這事『盖校” “怎么了扮授?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵芳室,是天一觀的道長。 經(jīng)常有香客問我刹勃,道長堪侯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任荔仁,我火速辦了婚禮伍宦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乏梁。我一直安慰自己次洼,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布遇骑。 她就那樣靜靜地躺著卖毁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪质蕉。 梳的紋絲不亂的頭發(fā)上势篡,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音模暗,去河邊找鬼禁悠。 笑死,一個胖子當著我的面吹牛兑宇,可吹牛的內(nèi)容都是我干的碍侦。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼隶糕,長吁一口氣:“原來是場噩夢啊……” “哼瓷产!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起枚驻,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤濒旦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后再登,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尔邓,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年锉矢,在試婚紗的時候發(fā)現(xiàn)自己被綠了梯嗽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡沽损,死狀恐怖灯节,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤炎疆,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布卡骂,位于F島的核電站,受9級特大地震影響磷雇,放射性物質(zhì)發(fā)生泄漏偿警。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一唯笙、第九天 我趴在偏房一處隱蔽的房頂上張望螟蒸。 院中可真熱鬧,春花似錦崩掘、人聲如沸七嫌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诵原。三九已至,卻和暖如春挽放,著一層夾襖步出監(jiān)牢的瞬間绍赛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工辑畦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吗蚌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓纯出,卻偏偏與公主長得像蚯妇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子暂筝,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350