當初查log相關資料,先找到了Log4j和common-logging的使用 ,而後找到這篇。由於寫的太好了,收藏下
一 :爲何同時使用commons-logging和Log4j?爲何不只使用其中之一?
Commons-loggin的目的是爲「全部的Java日誌實現」提供一個統一的接口,它自身的日誌功能日常弱(只有一個簡單的SimpleLog?),因此通常不會單獨使用它。Log4j的功能很是全面強大,是目前的首選。我發現幾乎全部的Java開源項目都會用到Log4j,但我同時發現,全部用到Log4j的項目通常也同時會用到commons-loggin。我想,你們都不但願本身的項目與Log4j綁定的太緊密吧。另一個我能想到的「同時使用commons-logging和Log4j」的緣由是,簡化使用和配置。
二 :Commons-logging能幫咱們作什麼?
提供一個統一的日誌接口,簡單了操做,同時避免項目與某個日誌實現系統緊密a耦合很貼心的幫咱們自動選擇適當的日誌實現系統(這一點很是好!)它甚至不須要配置
這裏看一下它怎麼「‘很貼心的’幫咱們‘自動選擇’‘適當的’日誌實現系統」:
1) 首先在classpath下尋找本身的配置文件commons-logging.properties,若是找到,則使用其中定義的Log實現類;
2) 若是找不到commons-logging.properties文件,則在查找是否已定義系統環境變量org.apache.commons.logging.Log,找到則使用其定義的Log實現類;
創建一個叫 :CATALINA_OPTS 的環境變量
給他的值 : - Dorg.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog - Dorg.apache.commons.logging.simplelog.defaultlog = warn
3) 不然,查看classpath中是否有Log4j的包,若是發現,則自動使用Log4j做爲日誌實現類;
4) 不然,使用JDK自身的日誌實現類(JDK1.4之後纔有日誌實現類);
5) 不然,使用commons-logging本身提供的一個簡單的日誌實現類SimpleLog;
(以上順序不保證徹底準確,請參考官方文檔)
可見,commons-logging老是能找到一個日誌實現類,而且儘量找到一個「最合適」的日誌實現類。我說它「很貼心」其實是由於:
一、能夠不須要配置文件;
二、自動判斷有沒有Log4j包,有則自動使用之;
三、最悲觀的狀況下也總能保證提供一個日誌實現(SimpleLog)。
能夠看到,commons-logging對編程者和Log4j都很是友好。
爲了簡化配置commons-logging,通常不使用commons-logging的配置文件,也不設置與commons-logging相關的系統環境變量,而只需將Log4j的Jar包放置到classpash中就能夠了。這樣就很簡單地完成了commons-logging與Log4j的融合。若是不想用Log4j了怎麼辦?只需將classpath中的Log4j的Jar包刪除便可。就這麼簡單!
代碼應該怎麼寫?
咱們在須要輸出日誌信息的「每一人」類中作以下的三個工做:
一、導入全部需的commongs-logging類:
代碼
1 import org.apache.commons.logging.Log;
2 import org.apache.commons.logging.LogFactory;
若是願意簡化的話,還能夠兩行合爲一行:
代碼
1 import org.apache.commons.logging. * ;
二、在本身的類中定義一個org.apache.commons.logging.Log類的私有靜態類成員:
代碼
1 private static Log log = LogFactory.getLog(YouClassName. class );
注意這裏定義的是static成員,以免產生多個實例。
LogFactory.getLog()方法的參數使用的是當前類的class,這是目前被普通認爲的最好的方式。爲何不寫做LogFactory.getLog(this.getClass())?由於static類成員訪問不到this指針!
三、使用org.apache.commons.logging.Log類的成員方法輸出日誌信息:
代碼
1 log.debug( " 111 " );
2 log.info( " 222 " );
3 log.warn( " 333 " );
4 log.error( " 444 " );
5 log.fatal( " 555 " );
這裏的log,就是上面第二步中定義的類成員變量,其類型是org.apache.commons.logging.Log,經過該類的成員方法,咱們就能夠將不一樣性質的日誌信息輸出到目的地(目的地是哪裏?視配置可定,多是stdout,也多是文件,還多是發送到郵件,甚至發送短信到手機……詳見下文對log4j.properties的介紹):
代碼
1 debug() 輸出「調試」級別的日誌信息;
2 info() 輸出「信息」級別的日誌信息;
3 warn() 輸出「警告」級別的日誌信息;
4 error() 輸出「錯誤」級別的日誌信息;
5 fatal() 輸出「致命錯誤」級別的日誌信息;
根據不一樣的性質,日誌信息一般被分紅不一樣的級別,從低到高依次是:
「調試(DEBUG)」「信息(INFO)」「警告(WARN)」「錯誤(ERROR)」「致命錯誤(FATAL)」。
爲何要把日誌信息分紅不一樣的級別呢?這其實是方便咱們更好的控制它。好比,經過Log4j的配置文件,咱們能夠設置「輸出‘調試’及以上級別的日誌信息」(即「調試」「信息」「警告」「錯誤」「致命錯誤」),這對項目開發人員多是有用的;咱們還能夠設置「輸出「警告」及以上級別的日誌信息」(即「警告」「錯誤」「致命錯誤」),這對項目最終用戶多是有用的。
僅從字面上理解,也能夠大體得出結論:最經常使用的應該是debug()和info();而warn()、error()、
fatal()僅在相應事件發生後才使用。
從上面三個步驟能夠看出,使用commons-logging的日誌接口很是的簡單,不須要記憶太多東西:僅僅用到了兩個類Log, LogFactory,而且兩個類的方法都很是少(後者只用到一個方法,前者常常用到的也只是上面第三步中列出的幾個),同時參數又很是簡單。
上面所介紹的方法是目前被普通應用的,能夠說是被標準化了的方法,幾乎全部的人都是這麼用。若是不信,或想確認一下,就去下載幾個知名的Java開源項目源代碼看一下吧。
下面給出一個完整的Java類的代碼:
代碼
1 package liigo.testlog;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5
6 public class TestLog {
7 private static Log log = LogFactory.getLog(TestLog. class );
8 public void test() {
9 log.debug( " 111 " );
10 log.info( " 222 " );
11 log.warn( " 333 " );
12 log.error( " 444 " );
13 log.fatal( " 555 " );
14 }
15
16 public static void main(String[] args) {
17 TestLog testLog = new TestLog();
18 testLog.test();
19 }
20 }
只要保證commons-logging的jar包在classpath中,上述代碼確定能夠很順利的編譯經過。那它的執行結果是怎麼樣的呢?恐怕會有很大的不一樣,請繼續往下看。
Log4j在哪裏呢?它發揮做用了嗎?
應該注意到,咱們上面給出的源代碼,徹底沒有涉及到Log4j——這正是咱們所但願的,這也正是commons-logging所要達到的目標之一。
但是,怎麼才能讓Log4j發揮它的做用呢?答案很簡單,只需知足「classpath中有Log4j的jar包」。前面已經說過了,commons-logging會自動發現並應用Log4j。因此只要它存在,它就發揮做用。(它不存在呢?天然就不發揮做用,commons-logging會另行選擇其它的日誌實現類。)
注意:配置文件log4j.properties對Log4j來講是必須的。若是classpath中沒有該配置文件,或者配置不對,將會引起運行時異常。
這樣,要正確地應用Log4j輸出日誌信息,log4j.properties的做用就很重要了。好在該文件有通用的模板,複製一份(稍加修改)就可使用。幾乎每個Java項目目錄內都會有一個log4j.properties文件,可下載幾個Java開源項目源代碼查看。本文最後也附一個模板性質的log4j.properties文件,直接複製過去就能夠用,或者根據本身的須要稍加修改。後文將會log4j.properties文件適看成一些介紹。
這裏順便提示一點:若是不用commons-logging,僅僅單獨使用Log4j,操做上反而要稍微麻煩一些,由於Log4j須要多一點點的初始化代碼(相比commons-logging而言):
代碼
1 import org.apache.log4j.Logger;
2 import org.apache.log4j.PropertyConfigurator;
3 public class TestLog4j {
4 static Logger logger = Logger.getLogger(TestLog4j. class ); // First step
5 public static void main(String args[]) {
6 PropertyConfigurator.configure( " log4j.properties " ); // Second step
7 logger.debug( " Here is some DEBUG " ); // Third step
8 logger.info( " Here is some INFO " );
9 logger.warn( " Here is some WARN " );
10 logger.error( " Here is some ERROR " );
11 logger.fatal( " Here is some FATAL " );
12 }
13 }
不過也就多出一行。但這至少說明,引用commons-logging並無使問題複雜化,反而簡單了一些。在這裏1+1就小於2了。這也驗證了前面的結論。
總結
將commons-logging和Log4j的jar包都放置到classpath下,同時也將Log4j的配置文件放到classpath中,二者就能夠很好的合做。
採用Log4j配合commons-logging做爲日誌系統,是目前Java領域很是很是流行的模式,使用很是很是的廣泛。二者的結合帶來的結果就是:簡單 + 強大。
commons-logging提供了簡捷、統一的接口,不須要額外配置,簡單;
Log4j功能很是全面、強大;
commons-logging僅僅對Log4j(固然還包括其它LOG實現)做了一層包裝,具體的日誌輸出仍是在內部轉交給身後的Log4j來處理;而Log4j雖然作了全部的事情,卻甘做綠葉,從不以真身示人。
二者堪稱絕配。
對log4j.properties的一點介紹
下面對log4j.properties文件內容做一點點介紹,之後文所附log4j.properties文件爲例:
除去以#開頭的註釋以及空行,第一行有用的內容是:
1 log4j.rootLogger = DEBUG, CONSOLE,A1
log4j.rootLogger是最最重要的一個屬性了,它定義日誌信息的「輸出級別」和「輸出目的地」。
關鍵看「=」後面的值,「DEBUG, CONSOLE,A1」這裏咱們要把它分紅兩部分:第一個逗號以前的是第一部分,指定「輸出級別」;後面的是第二部分,指定「輸出目的地」。能夠同時指定多個「輸出目的地」,以逗號隔開。
具體到上面這一行:它指定的「輸出級別」是「DEBUG」;它指定的「輸出目的地」是「CONSOLE」和「A1」。
注意:
「輸出級別」有可選的五個值,分別是DEBUG、INFO、WARN、ERROR、FATAL,它們是由Log4j系統定義的。
「輸出目的地」就是咱們本身定義的了,就在log4j.properties的後面部分,此文件定義的「輸出目的地」有CONSOLE、FILE、ROLLING_FILE、SOCKET、LF5_APPENDER、MAIL、DATABASE、A一、im。該文件之因此可做主模板,就是由於它比較全面地定義了各類常見的輸出目的地(控制檯、文件、電子郵件、數據庫等)。
好,下面詳細解釋「log4j.rootLogger=DEBUG, CONSOLE,A1」這一行:
指定「輸出級別」是「DEBUG」,即,僅輸出級別大於等於「調試(DEBUG)」的日誌信息。若是此處指定的是「WARN」則僅調用warn()、error()、fatal()方法輸出的日誌信息才被輸出到「輸出目的地」,而調用debug()、info()方法輸出的日誌信息不被輸出到「輸出目的地」。明白了嗎?Log4j就是以這種方式來過濾控制日誌信息的輸出與否,這也是對日誌信息進行級別分類的目的。
指定「輸出目的地」是「CONSOLE」和「A1」,即,將指定的日誌信息(根據日誌級別已進行了過濾)同時輸出到的「控制檯」和「SampleMessages.log4j文件」。
爲何說「CONSOLE」表示將日誌信息輸出到「控制檯」呢?那就要看一下後文的定義了:
# 應用於控制檯
1 log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender
2 log4j.appender.Threshold = DEBUG
3 log4j.appender.CONSOLE.Target = System.out
4 log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
5 log4j.appender.CONSOLE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
6 #log4j.appender.CONSOLE.layout.ConversionPattern = [start] % d {DATE} [DATE] % n % p[PRIORITY] % n % x[NDC] % n % t[THREAD] n % c[CATEGORY] % n % m[MESSAGE] % n % n
爲何說「A1」表示將日誌信息輸出到「SampleMessages.log4j文件」呢?還要看後文的定義:
1 log4j.appender.A1 = org.apache.log4j.DailyRollingFileAppender
2 log4j.appender.A1.File = SampleMessages.log4j
3 log4j.appender.A1.DatePattern = yyyyMMdd - HH ' .log4j '
4 log4j.appender.A1.layout = org.apache.log4j.xml.XMLLayout
注意:這裏的定義沒有指定輸出文件的路徑,它的路徑其實是 java.user.path的值。
您應該已經注意到,在定義「輸出目的地」時,還能夠指定日誌格式、時間、佈局等相關信息。略過。
好了,我能夠根據須要,將這一行修改成:
1 log4j.rootLogger = ERROR, CONSOLE,FILE,MAIL
將「錯誤(ERROR)」及「致命錯誤(FATAL)」級別的日誌信息同時輸出到控制檯、文件,而且發電子郵件向系統管理員報告。是否是很爽?(若是將「調試(DEBUG)」級別的日誌信息郵件給管理員,恐怕早晚會把他/她的郵箱漲爆,哪怕用的是Gmail!再次理解了「將日誌信息分爲不一樣級別」的意圖了吧?)
附:一個有用的log4j.properties文件模板
代碼
##Log4J的配置之簡單使它遍佈於愈來愈多的應用中了
##Log4J配置文件實現了輸出到控制檯、文件、回滾文件、發送日誌郵件、輸出到數據庫日誌表、自定義標籤等全套功能。擇其一二使用就夠用了。
##此文件(log4j.properties)內容來自網絡,非本文做者liigo原創。
log4j.rootLogger = DEBUG, CONSOLE,A1
log4j.addivity.org.apache = true
# 應用於控制檯
log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender
log4j.appender.Threshold = DEBUG
log4j.appender.CONSOLE.Target = System.out
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
#log4j.appender.CONSOLE.layout.ConversionPattern = [start] % d {DATE} [DATE] % n % p[PRIORITY] % n % x[NDC] % n % t[THREAD] n % c[CATEGORY] % n % m[MESSAGE] % n % n
#應用於文件
log4j.appender.FILE = org.apache.log4j.FileAppender
log4j.appender.FILE.File = file.log
log4j.appender.FILE.Append = false
log4j.appender.FILE.layout = org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
# Use this layout for LogFactor 5 analysis
# 應用於文件回滾
log4j.appender.ROLLING_FILE = org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold = ERROR
log4j.appender.ROLLING_FILE.File = rolling.log
log4j.appender.ROLLING_FILE.Append = true
log4j.appender.ROLLING_FILE.MaxFileSize = 10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex = 1
log4j.appender.ROLLING_FILE.layout = org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
#應用於socket
log4j.appender.SOCKET = org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost = localhost
log4j.appender.SOCKET.Port = 5001
log4j.appender.SOCKET.LocationInfo = true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout = org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern = [start] % d {DATE} [DATE] % n % p[PRIORITY] % n % x[NDC] % n % t[THREAD] % n % c[CATEGORY] % n % m[MESSAGE] % n % n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER = org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords = 2000
# 發送日誌給郵件
log4j.appender.MAIL = org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold = FATA
log4j.appender.MAIL.BufferSize = 10
log4j.appender.MAIL.From = web@www.wuset.com
log4j.appender.MAIL.SMTPHost = www.wusetu.com
log4j.appender.MAIL.Subject = Log4J Message
log4j.appender.MAIL.To = web@www.wusetu.com
log4j.appender.MAIL.layout = org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
# 用於數據庫
log4j.appender.DATABASE = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL = jdbc:mysql: // localhost:3306/test
log4j.appender.DATABASE.driver = com.mysql.jdbc.Driver
log4j.appender.DATABASE.user = root
log4j.appender.DATABASE.password =
log4j.appender.DATABASE.sql = INSERT INTO LOG4J (Message) VALUES ( ' [framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n ' )
log4j.appender.DATABASE.layout = org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
log4j.appender.A1 = org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File = SampleMessages.log4j
log4j.appender.A1.DatePattern = yyyyMMdd - HH ' .log4j '
log4j.appender.A1.layout = org.apache.log4j.xml.XMLLayout
#自定義Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout = org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern = [framework] % d - % c -%- 4r [ % t] %- 5p % c % x - % m % n
java