一、日志框架
1.1、選擇SLF4J而不是Log4j
我建議直接選擇SLF4J而不是Log4j,commons logging,logback或java.util.logging
1、在開源庫或內(nèi)部庫中使用SLF4J,將使其獨(dú)立于任何特定的日志記錄實(shí)現(xiàn),這意味著無需為多個(gè)庫管理多個(gè)日志記錄配置,您的客戶端將會(huì)很需要這一點(diǎn)。
2、SLF4J提供了基于占位符的日志記錄,通過刪除檢查(isDebugEnabled(),isInfoEnabled()等)來提高代碼的可讀性。
3、另外,臨時(shí)字符串?dāng)?shù)量越少意味著垃圾收集器的工作量就越少,這意味著應(yīng)用程序的吞吐量和性能會(huì)更好。
這些優(yōu)勢只是冰山一角,當(dāng)您開始使用SL4J深入了解它時(shí),您將看到更多的優(yōu)點(diǎn)。 我強(qiáng)烈建議,Java中的任何新代碼開發(fā)都應(yīng)該使用SLF4J來記錄日志。
1.2、log4j、logback、log4j2關(guān)系
日志的具體實(shí)現(xiàn),其中l(wèi)og4j和logback是基于SLF4J接口規(guī)范進(jìn)行實(shí)現(xiàn)的。
1.3、注意點(diǎn)
SLF4J、log4j、logback是一家公司出的。先有的log4j,后來發(fā)現(xiàn)性能有問題,在log4j上改造又太麻煩,所以直接重新開發(fā)個(gè)logback,但是為了規(guī)范和以后維護(hù)升級(jí),就出了一個(gè)規(guī)范SLF4J。而log4j2其實(shí)只是Apache出的一套日志框架,也很完美。
1.5 logback取代log4j的理由
(1)更快的實(shí)現(xiàn):Logback的內(nèi)核重寫了,在一些關(guān)鍵執(zhí)行路徑上性能提升10倍以上。而且logback不僅性能提升了,初始化內(nèi)存加載也更小了。
(2)非常充分的測試:Logback經(jīng)過了幾年,數(shù)不清小時(shí)的測試。Logback的測試完全不同級(jí)別的。
(3)Logback-classic非常自然實(shí)現(xiàn)了SLF4j:Logback-classic實(shí)現(xiàn)了SLF4j。在使用SLF4j中,你都感覺不到logback-classic。而且因?yàn)閘ogback-classic非常自然地實(shí)現(xiàn)了slf4j?, 所 以切換到log4j或者其他,非常容易,只需要提供成另一個(gè)jar包就OK,根本不需要去動(dòng)那些通過SLF4JAPI實(shí)現(xiàn)的代碼。
(4)非常充分的文檔官方網(wǎng)站有兩百多頁的文檔。
(5)自動(dòng)重新加載配置文件,當(dāng)配置文件修改了,Logback-classic能自動(dòng)重新加載配置文件。掃描過程快且安全,它并不需要另外創(chuàng)建一個(gè)掃描線程。這個(gè)技術(shù)充分保證了應(yīng)用程序能跑得很歡在JEE環(huán)境里面。
(6)Lilith是log事件的觀察者,和log4j的chainsaw類似。而lilith還能處理大數(shù)量的log數(shù)據(jù) 。
(7)謹(jǐn)慎的模式和非常友好的恢復(fù),在謹(jǐn)慎模式下,多個(gè)FileAppender實(shí)例跑在多個(gè)JVM下,能 夠安全地寫道同一個(gè)日志文件。RollingFileAppender會(huì)有些限制。Logback的FileAppender和它的子類包括 RollingFileAppender能夠非常友好地從I/O異常中恢復(fù)。
(8)配置文件可以處理不同的情況,開發(fā)人員經(jīng)常需要判斷不同的Logback配置文件在不同的環(huán)境下(開發(fā),測試,生產(chǎn))。而這些配置文件僅僅只有一些很小的不同,可以通過,和來實(shí)現(xiàn),這樣一個(gè)配置文件就可以適應(yīng)多個(gè)環(huán)境。
(9)Filters(過濾器)有些時(shí)候,需要診斷一個(gè)問題,需要打出日志。在log4j,只有降低日志級(jí)別,不過這樣會(huì)打出大量的日志,會(huì)影響應(yīng)用性能。在Logback,你可以繼續(xù) 保持那個(gè)日志級(jí)別而除掉某種特殊情況,如alice這個(gè)用戶登錄,她的日志將打在DEBUG級(jí)別而其他用戶可以繼續(xù)打在WARN級(jí)別。要實(shí)現(xiàn)這個(gè)功能只需加4行XML配置??梢詤⒖糓DCFIlter 。
(10)SiftingAppender(一個(gè)非常多功能的Appender):它可以用來分割日志文件根據(jù)任何一個(gè)給定的運(yùn)行參數(shù)。如,SiftingAppender能夠區(qū)別日志事件跟進(jìn)用戶的Session,然后每個(gè)用戶會(huì)有一個(gè)日志文件。
(11)自動(dòng)壓縮已經(jīng)打出來的log:RollingFileAppender在產(chǎn)生新文件的時(shí)候,會(huì)自動(dòng)壓縮已經(jīng)打出來的日志文件。壓縮是個(gè)異步過程,所以甚至對于大的日志文件,在壓縮過程中應(yīng)用不會(huì)受任何影響。
(12)堆棧樹帶有包版本:Logback在打出堆棧樹日志時(shí),會(huì)帶上包的數(shù)據(jù)。
(13)自動(dòng)去除舊的日志文件:通過設(shè)置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory屬性,你可以控制已經(jīng)產(chǎn)生日志文件的最大數(shù)量。如果設(shè)置maxHistory 12,那那些log文件超過12個(gè)月的都會(huì)被自動(dòng)移除。
二、Commons Logging簡介
common-logging是apache提供的一個(gè)通用的日志接口,
在common-logging中,有一個(gè)Simple logger的簡單實(shí)現(xiàn),但是它功能很弱,所以使用common-logging,通常都是配合著log4j來使用;
Commons Logging定義了一個(gè)自己的接口 org.apache.commons.logging.Log,以屏蔽不同日志框架的API差異,這里用到了Adapter Pattern(適配器模式)。
三、SLF4J簡介
3.1 slf4j是什么
SLF4J(Simple Logging Facade For Java);
是日志的門面,什么叫門面?就是日志的抽象層?再說詳細(xì)點(diǎn):就是一個(gè)接口規(guī)范,類似于JDBC那種,只提供一個(gè)門面,誰想要具體的,你們自己各大廠商去實(shí)現(xiàn)。比如目前的實(shí)現(xiàn)者:logback。
3.2 slf4j說明
Simple Logging Facade for Java(SLF4J)用作各種日志框架(例如java.util.logging,logback,log4j)的簡單外觀或抽象,允許最終用戶在部署時(shí)插入所需的日志框架。
要切換日志框架,只需替換類路徑上的slf4j綁定。 例如,要從java.util.logging切換到log4j,只需將slf4j-jdk14-1.8.0-beta2.jar替換為slf4j-log4j12-1.8.0-beta2.jar
SLF4J不依賴于任何特殊的類裝載機(jī)制。 實(shí)際上,每個(gè)SLF4J綁定在編譯時(shí)都是硬連線的,以使用一個(gè)且只有一個(gè)特定的日志記錄框架。 例如,slf4j-log4j12-1.8.0-beta2.jar綁定在編譯時(shí)綁定以使用log4j。 在您的代碼中,除了slf4j-api-1.8.0-beta2.jar之外,您只需將您選擇的一個(gè)且只有一個(gè)綁定放到相應(yīng)的類路徑位置。 不要在類路徑上放置多個(gè)綁定。
3.3 slf4j官網(wǎng)
3.4 slf4j關(guān)系圖

3.5 sl4j集成
因此,slf4j就是眾多日志接口的集合,他不負(fù)責(zé)具體的日志實(shí)現(xiàn),只在編譯時(shí)負(fù)責(zé)尋找合適的日志系統(tǒng)進(jìn)行綁定。具體有哪些接口,全部都定義在slf4j-api中。查看slf4j-api源碼就可以發(fā)現(xiàn),里面除了public final class LoggerFactory類之外,都是接口定義。因此,slf4j-api本質(zhì)就是一個(gè)接口定義。
總之,Slf4j更好的兼容了各種具體日志實(shí)現(xiàn)的框架,如圖:

四、log4j簡介
4.1 Log4j是什么
Log4j是Apache的一個(gè)開放源代碼項(xiàng)目,通過使用Log4j,我們可以控制日志信息輸送的;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級(jí)別,我們能夠更加細(xì)致地控制日志的生成過程。最令人感興趣的就是,這些可以通過一個(gè)配置文件來靈活地進(jìn)行配置,而不需要修改應(yīng)用的代碼。
4.2配置根Logger
Logger負(fù)責(zé)處理日志記錄的大部分操作。?
其語法為:
log4j.rootLogger = [ level ] , appenderName, appenderName, …?
其中, level 是日志記錄的優(yōu)先級(jí),分為 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 ALL 或者自定義的級(jí)別。 Log4j 建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是 ERROR 、 WARN 、 INFO 、 DEBUG 。通過在這里定義的級(jí)別,您可以控制到應(yīng)用程序中相應(yīng)級(jí)別的日志信息的開關(guān)。比如在這里定義了 INFO 級(jí)別,只有等于及高于這個(gè)級(jí)別的才進(jìn)行處理,則應(yīng)用程序中所有 DEBUG 級(jí)別的日志信息將不被打印出來。 ALL: 打印所有的日志, OFF :關(guān)閉所有的日志輸出。 appenderName 就是指定日志信息輸出到哪個(gè)地方??赏瑫r(shí)指定多個(gè)輸出目的地。?
4.3?Appender?
配置日志信息輸出目的地Appender負(fù)責(zé)控制日志記錄操作的輸出。?
其語法為:
log4j.appender.appenderName = fully.qualified.name.of.appender.class?
log4j.appender.appenderName.option1 = value1?
log4j.appender.appenderName.optionN = valueN?
其中,Log4j提供的 appender 有以下幾種:?
org.apache.log4j.ConsoleAppender(控制臺(tái)),?
org.apache.log4j.FileAppender(文件),?
org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件),?
org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件),可通過 log4j.appender.R.MaxFileSize=100KB 設(shè)置文件大小,還可通過 log4j.appender.R.MaxBackupIndex=1 設(shè)置為保存一個(gè)備份文件。?
org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)?
例:
log4j.appender.stdout=org.apache.log4j.ConsoleAppender?
定義一個(gè)名為stdout的輸出目的地, ConsoleAppender 為控制臺(tái)。?
4.4?Layout?
其中,Log4j提供的 layout 有以下幾種:?
org.apache.log4j.HTMLLayout(以 HTML 表格形式布局),?
org.apache.log4j.PatternLayout(可以靈活地指定布局模式),?
org.apache.log4j.SimpleLayout(包含日志信息的級(jí)別和信息字符串),?
org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程、類別等等信息)?
4.5格式化日志信息
Log4j可以指定不同的日志信息打印格式,打印參數(shù)如下:?
%m輸出代碼中指定的消息?
%p輸出優(yōu)先級(jí),即 DEBUG , INFO , WARN , ERROR , FATAL?
%r輸出自應(yīng)用啟動(dòng)到輸出該 log 信息耗費(fèi)的毫秒數(shù)?
%c輸出所屬的類目,通常就是所在類的全名?%t ? ?輸出產(chǎn)生該日志事件的線程名?
%n輸出一個(gè)回車換行符, Windows 平臺(tái)為 “rn” , Unix 平臺(tái)為 “n”?
%d輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為 ISO8601 ,也可以在其后指定格式,比如: %d{yyyy MMM dd HH:mm:ss,SSS} ,輸出類似: 2014-10-08 11:34:27.501
%l輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。
4.6示例
一段簡單的log4j配置備用:
### set log levels ###log4j.rootLogger = debug,stdout,D,E###輸出到控制臺(tái) ###log4j.appender.stdout?= org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target = System.outlog4j.appender.stdout.layout = org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern = ?%-d{yyyy-MM-dd HH:mm:ss} ?[ %t:%r ] - [ %p ] ?%m%n###輸出到日志文件 ###log4j.appender.D = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.D.File = logs/log.loglog4j.appender.D.Append =?truelog4j.appender.D.Threshold = INFOlog4j.appender.D.layout = org.apache.log4j.PatternLayoutlog4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} ?[ %t:%r ] - [ %p ] ?%m%nlog4j.appender.D.DatePattern =?'.'yyyy-MM-dd###保存異常信息到單獨(dú)文件 ###log4j.appender.E = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.E.File = logs/error.loglog4j.appender.E.Append =?truelog4j.appender.E.Threshold = ERRORlog4j.appender.E.layout = org.apache.log4j.PatternLayoutlog4j.appender.E.DatePattern =?'.'yyyy-MM-dd-HH-mmlog4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} ?[ %t:%r ]?
五、logback簡介
5.1 logback模塊
Logback是由log4j創(chuàng)始人設(shè)計(jì)的另一個(gè)開源日志組件,官方網(wǎng)站: http://logback.qos.ch。它當(dāng)前分為下面下個(gè)模塊:
(1)logback-core:其它兩個(gè)模塊的基礎(chǔ)模塊
(2)logback-classic:它是log4j的一個(gè)改良版本,同時(shí)它完整實(shí)現(xiàn)了slf4j API使你可以很方便地更換成其它日志系統(tǒng)如log4j或JDK14 Logging
(3)logback-access:訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能
5.2 logback中三個(gè)重要概念
Logger:日志記錄器,把它關(guān)聯(lián)到應(yīng)用對應(yīng)的context上后,主要用于存放日志對象,定義日志類型,級(jí)別。
Appender: 指定日志輸出的目的地,目的地可以是控制臺(tái),文件,或者數(shù)據(jù)庫等
Layout:負(fù)責(zé)把事件轉(zhuǎn)換成字符串,格式化日志信息的輸出
5.3 logback配置優(yōu)先級(jí)順序
(1)logback首先在classpath尋找logback.groovy文件,
(2)如果沒找到,繼續(xù)尋找logback-test.xml文件
(3)如果沒找到,繼續(xù)尋找logback.xml文件
(4)如果仍然沒找到,則使用默認(rèn)配置(打印到控制臺(tái)