說到日誌工具,平常工做或學習中確定聽過這些名詞:log4j、logback、jdk-logging、slf4j、commons-logging等,它們之間有什麼關係,在整個日誌體系中又扮演什麼角色呢?
日誌框架分爲三大類,包括日誌門面、日誌適配器、日誌庫。利用門面設計模式,即Facade來進行解耦,使日誌使用變得更簡單。java
門面設計模式是面向對象設計模式中的一種,日誌框架採用的就是這種模式,相似JDBC的設計理念。它只提供一套接口規範,自身不負責日誌功能的實現,目的是讓使用者不須要關注底層具體是哪一個日誌庫來負責日誌打印機具體的使用細節等。目前用得最爲普遍的日誌門面有兩種:slf4j和commons-loggingweb
它巨頭實現了日誌的相關功能,主流的日誌庫有三個,分別是log4j、log-jdk、logback。最先Java想要記錄日誌只能經過System.out或System.err來完成,很是不方便。log4j就是爲了解決這一問題而提出的,它是最先誕生的日誌庫。接着JDK也在1.4版本引入了一個日誌庫java.util.logging.Logger,簡稱log-jdk。這樣市面上就出現了兩種日誌功能的實現,開發者在使用時須要關注所使用的日誌庫的具體細節。logback是最晚出現的,它與log4j出自同一個做者,是log4j的升級版且自己就實現了slf4j的接口。apache
日誌適配器分爲兩種場景:編程
日誌門面適配器,由於slf4j規範是後來提出的,在此以前的日誌庫是沒有實現slf4j的接口的,例如log4j.因此,在工程裏要想使用slf4j+log4j的模式,就額外須要一個適配器(slf4j+log4j12)來解決接口不兼容的問設計模式
日誌庫適配器,在一些老的工程裏,一開始爲了開發簡單而直接使用了日誌庫API來完成日誌打印,隨着時間的推移想將原來直接調用日誌庫的模式改成業界標準的門面模式(例如slf4j+logback組合),但老工程代碼裏打印日誌的地方太多,難以改動,因此須要一個適配器來完成從舊日誌庫的API到slf4j的路由,這樣在不改動原有代碼的狀況下也能使用slf4j來統一管理日誌,並且後續自由替換具體日誌庫也不是問題。api
若是是新工程,則推薦使用slf4j+logback模式,由於logback自身實現了slf4j的接口,不須要額外引入適配器,另外logback是log4j的升級版,具有比log4j更多的優勢,可經過以下配置進行集成:架構
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j-api.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback-core.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback-classic.version}</version> </dependency>
若是是老工程,則須要根據所使用的日誌庫來肯定門面適配器,一般狀況下老工程使用的都是log4j,所以以log4j日誌庫爲例,可經過以下配置進行集成:app
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j-api.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j-log4j12.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency>
若是老代碼直接使用了log4j日誌庫提供的接口來打印日誌,則還須要引入日誌庫適配器,配置實例以下所示:框架
<dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${log4j-over-slf4j.version}</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true"> <property name="application_name" value="web" /> <property name="LOG_PATH" value="c:" /> <!-- 控制檯輸出 --> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="UTF-8"> <pattern>%date %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern> <!-- <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern> --> </encoder> </appender> <!-- 時間滾動輸出 文件日誌 --> <appender name="file—debug" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>debug</level> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_debug.%d{yyyy-MM-dd}_%i.log</FileNamePattern> <MaxHistory>100</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10mb</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder charset="UTF-8"> <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern> </encoder> </appender> <!-- 時間滾動輸出 文件日誌 --> <appender name="file—info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>info</level> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_info.%d{yyyy-MM-dd}_%i.log</FileNamePattern> <MaxHistory>100</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10mb</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder charset="UTF-8"> <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern> </encoder> </appender> <!-- 時間滾動輸出 level爲 ERROR 日誌 --> <appender name="file—error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_error.%d{yyyy-MM-dd}_%i.log</FileNamePattern> <MaxHistory>100</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>10mb</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder charset="UTF-8"> <pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern> </encoder> </appender> <Logger name="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" level="DEBUG" additivity="false"> <appender-ref ref="file—debug" /> </Logger> <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender"> <!-- 不丟失日誌.默認的,若是隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日誌 --> <discardingThreshold>0</discardingThreshold> <!-- 更改默認的隊列的深度,該值會影響性能.默認值爲256 --> <queueSize>256</queueSize> <!-- 添加附加的appender,最多隻能添加一個 --> <appender-ref ref="file—error"/> </appender> <root level="info"> <appender-ref ref="stdout" /> <appender-ref ref="file—info" /> <appender-ref ref="file—error" /> </root> </configuration>
實例代碼以下:maven
private static final Logger logger =LoggerFactory.getLogger(ConfigureQuartz.class);
注意,logger對象被定義爲static變量,這是由於這個logger與當前類綁定,避免每次都new一個新對象,形成資源浪費,甚至引起OutOfMemoryError問題。
在使用slf4j+具體日誌庫模式時,因爲slf4j至關於充當api抽象接口,因此咱們的日誌打印是也是面向接口編程的,當咱們須要更換具體的日誌庫時,咱們只須要引入具體的maven依賴就能夠了,並對原有的日誌庫依賴進行移除,而不須要改動代碼。至此,slf4j的架構原理講解完成,以後會對具體的日誌庫logback的配置文件進行講解,本章只是先簡單給出logback.xml配置文件的基本模板,下一章節《日誌系列2——logback配置文件詳解》敬請期待。