老板下了死命令,要把日志系統(tǒng)切換到Logback
Log4j 介紹過了,SLF4J 也介紹過了,那接下來,你懂的,Logback 就要隆重地登場了,畢竟它哥仨有一個爹,那就是巨佬 Ceki Gulcu。
就在昨天,老板聽我說完 Logback 有多牛逼之后,徹底動心了,對我下了死命令,“這么好的日志系統(tǒng),你還不趕緊點,把它切換到咱的項目當(dāng)中!”
我們項目之前用的 Log4j,在我看來,已經(jīng)足夠用了,畢竟是小公司,性能上的要求沒那么苛刻。

01、Logback 強(qiáng)在哪
1)非常自然地實現(xiàn)了 SLF4J,不需要像 Log4j 和 JUL 那樣加一個適配層。

2)Spring Boot 的默認(rèn)日志框架使用的是 Logback。一旦某款工具庫成為了默認(rèn)選項,那就說明這款工具已經(jīng)超過了其他競品。

注意看下圖(證據(jù)找到了,來自 Spring Boot 官網(wǎng)):

也可以通過源碼的形式看得到:

3)支持自動重新加載配置文件,不需要另外創(chuàng)建掃描線程來監(jiān)視。
4)既然是巨佬的新作,那必然在性能上有了很大的提升,不然呢?
02、Logback 使用示例
第一步,在 pom.xml 文件中添加 Logback 的依賴:
<dependency>
????<groupId>ch.qos.logbackgroupId>
????<artifactId>logback-classicartifactId>
????<version>1.2.3version>
dependency>
Maven 會自動導(dǎo)入另外兩個依賴:

logback-core 是 Logback 的核心,logback-classic 是 SLF4J 的實現(xiàn)。
第二步,來個最簡單的測試用例:
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;
/**
?*?@author?微信搜「沉默王二」,回復(fù)關(guān)鍵字?PDF
?*/
public?class?Test?{
????static?Logger?logger?=?LoggerFactory.getLogger(Test.class);
????public?static?void?main(String[]?args)?{
????????logger.debug("logback");
????}
}
Logger 和 LoggerFactory 都來自 SLF4J,所以如果項目是從 Log4j + SLF4J 切換到 Logback 的話,此時的代碼是零改動的。
運(yùn)行 Test 類,可以在控制臺看到以下信息:
12:04:20.149?[main]?DEBUG?com.itwanger.Test?-?logback
在沒有配置文件的情況下,一切都是默認(rèn)的,Logback 的日志信息會輸出到控制臺。可以通過 StatusPrinter 來打印 Logback 的內(nèi)部信息:
LoggerContext?lc?=?(LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
在 main 方法中添加以上代碼后,再次運(yùn)行 Test 類,可以在控制臺看到以下信息:
12:59:22.314?[main]?DEBUG?com.itwanger.Test?-?logback
12:59:22,261?|-INFO?in?ch.qos.logback.classic.LoggerContext[default]?-?Could?NOT?find?resource?[logback-test.xml]
12:59:22,262?|-INFO?in?ch.qos.logback.classic.LoggerContext[default]?-?Could?NOT?find?resource?[logback.groovy]
12:59:22,262?|-INFO?in?ch.qos.logback.classic.LoggerContext[default]?-?Could?NOT?find?resource?[logback.xml]
12:59:22,268?|-INFO?in?ch.qos.logback.classic.BasicConfigurator@5e853265?-?Setting?up?default?configuration.
也就是說,Logback 會在 classpath 路徑下先尋找 logback-test.xml 文件,沒有找到的話,尋找 logback.groovy 文件,還沒有的話,尋找 logback.xml 文件,都找不到的話,就輸出到控制臺。
一般來說,我們會在本地環(huán)境中配置 logback-test.xml,在生產(chǎn)環(huán)境下配置 logback.xml。
**第三步,**在 resource 目錄下增加 logback-test.xml 文件,內(nèi)容如下所示:
<configuration?debug="true">
????<appender?name="STDOUT"?class="ch.qos.logback.core.ConsoleAppender">
????????<encoder>
????????????<pattern>%d{HH:mm:ss.SSS}?%relative?[%thread]?%-5level?%logger{36}?-?%msg%npattern>
????????encoder>
????appender>
????<root?level="debug">
????????<appender-ref?ref="STDOUT"?/>
????root>
configuration>
Logback 的配置文件非常靈活,最基本的結(jié)構(gòu)為 元素,包含 0 或多個 元素,其后跟 0 或多個 元素,其后再跟最多只能存在一個的 元素。

1)配置 appender,也就是配置日志的輸出目的地,通過 name 屬性指定名字,通過 class 屬性指定目的地:
ch.qos.logback.core.ConsoleAppender:輸出到控制臺。 ch.qos.logback.core.FileAppender:輸出到文件。 ch.qos.logback.core.rolling.RollingFileAppender:文件大小超過閾值時產(chǎn)生一個新文件。
除了輸出到本地,還可以通過 SocketAppender 和 SSLSocketAppender 輸出到遠(yuǎn)程設(shè)備,通過 SMTPAppender 輸出到郵件。甚至可以通過 DBAppender 輸出到數(shù)據(jù)庫中。
encoder 負(fù)責(zé)把日志信息轉(zhuǎn)換成字節(jié)數(shù)組,并且把字節(jié)數(shù)組寫到輸出流。
pattern 用來指定日志的輸出格式:
%d:輸出的時間格式。%thread:日志的線程名。%-5level:日志的輸出級別,填充到 5 個字符。比如說 info 只有 4 個字符,就填充一個空格,這樣日志信息就對齊了。
反例(沒有指定 -5 的情況):

%logger{length}:logger 的名稱,length 用來縮短名稱。沒有指定表示完整輸出;0 表示只輸出 logger 最右邊點號之后的字符串;其他數(shù)字表示輸出小數(shù)點最后邊點號之前的字符數(shù)量。%msg:日志的具體信息。%n:換行符。%relative:輸出從程序啟動到創(chuàng)建日志記錄的時間,單位為毫秒。
2)配置 root,它只支持一個屬性——level,值可以為:TRACE、DEBUG、INFO、WARN、ERROR、ALL、OFF。
appender-ref 用來指定具體的 appender。
3)查看內(nèi)部狀態(tài)信息。
可以在代碼中通過 StatusPrinter 來打印 Logback 內(nèi)部狀態(tài)信息,也可以通過在 configuration 上開啟 debug 來打印內(nèi)部狀態(tài)信息。
重新運(yùn)行 Test 類,可以在控制臺看到以下信息:
13:54:54,718?|-INFO?in?ch.qos.logback.classic.LoggerContext[default]?-?Found?resource?[logback-test.xml]?at?[file:/Users/maweiqing/Documents/GitHub/JavaPointNew/codes/logbackDemo/target/classes/logback-test.xml]
13:54:54,826?|-INFO?in?ch.qos.logback.core.joran.action.AppenderAction?-?About?to?instantiate?appender?of?type?[ch.qos.logback.core.ConsoleAppender]
13:54:54,828?|-INFO?in?ch.qos.logback.core.joran.action.AppenderAction?-?Naming?appender?as?[STDOUT]
13:54:54,833?|-INFO?in?ch.qos.logback.core.joran.action.NestedComplexPropertyIA?-?Assuming?default?type?[ch.qos.logback.classic.encoder.PatternLayoutEncoder]?for?[encoder]?property
13:54:54,850?|-INFO?in?ch.qos.logback.classic.joran.action.RootLoggerAction?-?Setting?level?of?ROOT?logger?to?DEBUG
13:54:54,850?|-INFO?in?ch.qos.logback.core.joran.action.AppenderRefAction?-?Attaching?appender?named?[STDOUT]?to?Logger[ROOT]
13:54:54,850?|-INFO?in?ch.qos.logback.classic.joran.action.ConfigurationAction?-?End?of?configuration.
13:54:54,851?|-INFO?in?ch.qos.logback.classic.joran.JoranConfigurator@f8c1ddd?-?Registering?current?configuration?as?safe?fallback?point
13:54:54.853?[main]?DEBUG?com.itwanger.Test?-?logback
4)自動重載配置。
之前提到 Logback 很強(qiáng)的一個功能就是支持自動重載配置,那想要啟用這個功能也非常簡單,只需要在 configuration 元素上添加 scan=true 即可。
"true">
????...
默認(rèn)情況下,掃描的時間間隔是一分鐘一次。如果想要調(diào)整時間間隔,可以通過 scanPeriod 屬性進(jìn)行調(diào)整,單位可以是毫秒(milliseconds)、秒(seconds)、分鐘(minutes)或者小時(hours)。
下面這個示例指定的時間間隔是 30 秒:
"true"?scanPeriod="30?seconds"
???...
注意:如果指定了時間間隔,沒有指定時間單位,默認(rèn)的時間單位為毫秒。
當(dāng)設(shè)置 scan=true 后,Logback 會起一個 ReconfigureOnChangeTask 的任務(wù)來監(jiān)視配置文件的變化。
03、把 log4j.properties 轉(zhuǎn)成 logback-test.xml
如果你的項目以前用的 Log4j,那么可以通過下面這個網(wǎng)址把 log4j.properties 轉(zhuǎn)成 logback-test.xml:
http://logback.qos.ch/translator/
把之前 log4j.properties 的內(nèi)容拷貝一份:
###?設(shè)置###
log4j.rootLogger?=?debug,stdout,D,E
###?輸出信息到控制臺?###
log4j.appender.stdout?=?org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target?=?System.out
log4j.appender.stdout.layout?=?org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern?=?[%-5p]?%d{yyyy-MM-dd?HH:mm:ss,SSS}?method:%l%n%m%n
###?輸出DEBUG?級別以上的日志到=debug.log?###
log4j.appender.D?=?org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File?=?debug.log
log4j.appender.D.Append?=?true
log4j.appender.D.Threshold?=?DEBUG?
log4j.appender.D.layout?=?org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern?=?%d{yyyy-MM-dd?HH:mm:ss}??[?%t:%r?]?-?[?%p?]??%m%n
###?輸出ERROR?級別以上的日志到=error.log?###
log4j.appender.E?=?org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File?=error.log?
log4j.appender.E.Append?=?true
log4j.appender.E.Threshold?=?ERROR?
log4j.appender.E.layout?=?org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern?=?%d{yyyy-MM-dd?HH:mm:ss}??[?%t:%r?]?-?[?%p?]??%m%n
粘貼到該網(wǎng)址的文本域:

點擊「Translate」,可以得到以下內(nèi)容:
"1.0"?encoding="UTF-8"?>
??"stdout"?class="ch.qos.logback.core.ConsoleAppender">
????System.out
????
??????[%-5p]?%d{yyyy-MM-dd?HH:mm:ss,SSS}?method:%l%n%m%n
????
??
??"D"?class="ch.qos.logback.core.rolling.RollingFileAppender">
????
????
????
????true
????debug.log
????
??????%d{yyyy-MM-dd?HH:mm:ss}?[?%t:%r?]?-?[?%p?]?%m%n
????
????"ch.qos.logback.classic.filter.ThresholdFilter">
??????DEBUG
????
??
??"E"?class="ch.qos.logback.core.rolling.RollingFileAppender">
????
????
????
????error.log
????true
????
??????%d{yyyy-MM-dd?HH:mm:ss}?[?%t:%r?]?-?[?%p?]?%m%n
????
????"ch.qos.logback.classic.filter.ThresholdFilter">
??????ERROR
????
??
??"debug">
????"stdout"/>
????"D"/>
????"E"/>
??
可以確認(rèn)一下內(nèi)容,發(fā)現(xiàn)三個 appender 都在。

但是呢,轉(zhuǎn)換后的文件并不能直接使用,需要稍微做一些調(diào)整,因為:
第一,日志的格式化有細(xì)微的不同,Logback 中沒有 %l。
第二,RollingFileAppender 需要指定 RollingPolicy 和 TriggeringPolicy,前者負(fù)責(zé)日志的滾動功能,后者負(fù)責(zé)日志滾動的時機(jī)。如果 RollingPolicy 也實現(xiàn)了 TriggeringPolicy 接口,那么只需要設(shè)置 RollingPolicy 就好了。
TimeBasedRollingPolicy 和 SizeAndTimeBasedRollingPolicy 是兩種最常用的滾動策略。
TimeBasedRollingPolicy 同時實現(xiàn)了 RollingPolicy 與 TriggeringPolicy 接口,因此使用 TimeBasedRollingPolicy 的時候就可以不指定 TriggeringPolicy。
TimeBasedRollingPolicy 可以指定以下屬性:
fileNamePattern,用來定義文件的名字(必選項)。它的值應(yīng)該由文件名加上一個
%d的占位符。%d應(yīng)該包含java.text.SimpleDateFormat中規(guī)定的日期格式,缺省是yyyy-MM-dd。滾動周期是通過 fileNamePattern 推斷出來的。maxHistory,最多保留多少數(shù)量的日志文件(可選項),將會通過異步的方式刪除舊的文件。比如,你指定按月滾動,指定
maxHistory = 6,那么 6 個月內(nèi)的日志文件將會保留,超過 6 個月的將會被刪除。totalSizeCap,所有日志文件的大?。蛇x項)。超出這個大小時,舊的日志文件將會被異步刪除。需要配合 maxHistory 屬性一起使用,并且是第二條件。
來看下面這個 RollingFileAppender 配置:
"D"?class="ch.qos.logback.core.rolling.RollingFileAppender">
????debug.log
????"ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
????????
????????debug.%d{yyyy-MM-dd}.log
????????
????????30
????????3GB
????
????
????????%relative?[%thread]?%level?%logger{35}?-?%msg%n
????
基于按天滾動的文件策略,最多保留 30 天,最大大小為 30G。
SizeAndTimeBasedRollingPolicy 比 TimeBasedRollingPolicy 多了一個日志文件大小設(shè)定的屬性:maxFileSize,其他完全一樣。
基于我們對 RollingPolicy 的了解,可以把 logback-test.xml 的內(nèi)容調(diào)整為以下內(nèi)容:
????"stdout"?class="ch.qos.logback.core.ConsoleAppender">
????????System.out
????????
????????????%d{HH:mm:ss.SSS}?[%thread]?%level?%logger{36}?-?%msg%n
????????
????
"D"?class="ch.qos.logback.core.rolling.RollingFileAppender">
????true
????debug.log
????"ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
????????
????????debug.%d{yyyy-MM-dd}.log
????????
????????30
????????3GB
????
????
????????%relative?[%thread]?%-5level?%logger{35}?-?%msg%n
????
????"E"?class="ch.qos.logback.core.rolling.RollingFileAppender">
????????error.log
????????"ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
????????????
????????????error.%d{yyyy-MM-dd}.log
????????????
????????????30
????????????3GB
????????
????????
????????????%d{yyyy-MM-dd?HH:mm:ss}?[?%t:%r?]?-?[?%p?]?%m%n
????????
????????"ch.qos.logback.classic.filter.ThresholdFilter">
????????????ERROR
????????
????
????"debug">
????????"stdout"/>
????????"D"/>
????????"E"/>
????
修改 Test 類的內(nèi)容:
public?class?Test?{
????static?Logger?logger?=?LoggerFactory.getLogger(Test.class);
????public?static?void?main(String[]?args)?{
????????logger.debug("logback");
????????logger.error("logback");
????}
}
運(yùn)行后,可以在 target 目錄下看到兩個文件:debug.log 和 errror.log。

到此為止,項目已經(jīng)從 Log4j 切換到 Logback 了,過程非常的絲滑順暢,嘿嘿。
04、Logback 手冊
Logback 的官網(wǎng)上是有一份手冊的,非常詳細(xì),足足 200 多頁,只不過是英文版的。小伙伴們可以看完我這篇文章入門實操的 Logback 教程后,到下面的地址看官方手冊。
http://logback.qos.ch/manual/index.html
如果英文閱讀能力有限的話,可以到 GitHub 上查看雷鋒翻譯的中文版:
https://github.com/itwanger/logback-chinese-manual
當(dāng)然了,還有一部分小伙伴喜歡看離線版的 PDF,我已經(jīng)整理好了:
鏈接:https://pan.baidu.com/s/16FrbwycYUUIfKknlLhRKYA ?密碼:bptl
實話實話吧,白嫖的感覺就是舒服,趕緊去下載吧!

