slf4j log4j logback關係詳解和相關用法

slf4j log4j logback關係詳解和相關用法

寫java也有一段時間了,一直都有用slf4j log4j輸出日誌的習慣。但是始終都是抱着“拿來主義”的態度,複製粘貼下配置文件就開始編碼了,於是這段時間詳細的看了下日誌庫。

slf4j log4j logback的關係

The Simple Logging Facade for Java是什麼?

籠統的講就是slf4j是一系列的日誌接口,而log4j logback是具體實現了的日誌框架。接下來我們跟着官方文檔詳細的來看一下他們的關係。

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, logback and log4j. SLF4J allows the end-user to plug in the desired logging framework at deployment time. Note that SLF4J-enabling your library/application implies the addition of only a single mandatory dependency, namely slf4j-api-1.7.21.jar.

官方文檔的這一段話已經明確描述了三者的關係。slf4j譯爲簡單日誌門面,是日誌框架的抽象。而log4j和logback是衆多日誌框架中的幾種。

這裏寫了幾行簡單的代碼來驗證一下。

public class Program {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Program.class);
        logger.info("hello world");
    }
}

從運行結果可以看到,由於沒有給出具體的logger實現,無法在控制檯輸出日誌。也就是說我們在具體開發中,需要綁定一個日誌框架,才能正常的使用slf4j。

log4j和logback呢?

而log4j和logback就是兩個受歡迎的日誌框架。但兩者又有不同。

  • log4j是apache實現的一個開源日誌組件。(Wrapped implementations)
  • logback同樣是由log4j的作者設計完成的,擁有更好的特性,用來取代log4j的一個日誌框架。是slf4j的原生實現。(Native implementations)

enter image description here
上圖可以看到應用程序對日誌框架的調用關係。應用程序調用slf4j api,而日誌的輸出最終是由底層的日誌框架來實現的。這張圖也提現了log4j和logback的不同。

官方文檔對logback的描述

NATIVE IMPLEMENTATION There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements SLF4J natively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.

可以看到logback是直接實現了slf4j的接口,是不消耗內存和計算開銷的。而log4j不是對slf4j的原生實現,所以slf4j api在調用log4j時需要一個適配層。

總結:

  1. slf4j是java的一個日誌門面,實現了日誌框架一些通用的api,log4j和logback是具體的日誌框架。
  2. 他們可以單獨的使用,也可以綁定slf4j一起使用。
  • 單獨使用。分別調用框架自己的方法來輸出日誌信息。
  • 綁定slf4j一起使用。調用slf4j的api來輸入日誌信息,具體使用與底層日誌框架無關(需要底層框架的配置文件)

顯然這裏我們不推薦單獨使用日誌框架。假設項目中已經使用了log4j,而我們此時加載了一個類庫,而這個類庫依賴另一個日誌框架。這個時候我們就需要維護兩個日誌框架,這是一個非常麻煩的事情。而使用了slf4j就不同了,由於應用調用的抽象層的api,與底層日誌框架是無關的,因此可以任意更換日誌框架。

使用slf4j綁定日誌系統的優勢

  • 軟件工程的角度。抽象,解耦,便於維護。可以參考一下上面的例子。
  • 語法設計角度。slf4j有{}佔位符,而log4j需要用“+”來連接字符串,既不利於閱讀,同時消耗了內存(heap memory)。
  • 詳細的描述可以參考:http://www.importnew.com/7450.html

log4j與logback

作爲log4j的開發者,對log4j一定不陌生,他是apache的一個開源日誌框架。而logback相對於log4j來說,更新一點,是由log4j的作者設計實現的,第一個版本是2011推出的。無論從設計上還是實現上,Logback相對log4j而言有了相對多的改進。但是兩者的用法幾乎差別不大。下面是logback的優勢:

  • 更快的執行速度
  • 充分的測試
  • logback-classic 非常自然的實現了SLF4J
  • 豐富的擴展文檔
  • 可以使用使用XML配置文件或者Groovy
  • 自動重新載入配置文件
  • 優雅地從I/O錯誤中恢復
  • 自動清除舊的日誌歸檔文件
  • 自動壓縮歸檔日誌文件
  • 更多優點可以參考官方文檔。中文版 英文版

以上,從性能的角度,可以儘快從log4j遷移到logback上來。

slf4j綁定log4j的用法

由於現在log4j使用的還比較多,所以介紹下他的基本用法。

ide相關設置

這裏我們使用的IntelliJ IDEA2016.1和maven。

  1. 在pom.xml添加相關依賴。
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

此時會自動添加三個jar包。

配置文件

log4j的正常運行需要配置文件,配置文件類型:log4j配置文件可以是log4j.xml也可以是log4j.properties。需要爲其配置root、appender、layout等信息。

雖然網上大多數教程都是用log4j.properties來配置的(鍵值對),但是我個人覺得用xml配置,節點更清晰,而且在idea下有代碼提示,可以降低配置錯誤的概率。下面我就就不具體講配置文件了,只提幾個關鍵的地方。

  1. 必須配置root logger和一個appender。
  2. 日誌輸出級別,由高到低爲

        FATAL        
        ERROR      
        WARN        
        INFO        
        DEBUG    

下面給出配置文件。

<?xml version="1.0"  encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>

    <!--若干個appender的定義-->
    <!--org.apache.log4j.ConsoleAppender 輸出到控制檯-->
    <appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
        <!--輸出格式-->
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n"/>
        </layout>
    </appender>

    <!--org.apache.log4j.DailyRollingFileAppender 每天產生一個日誌文件-->
    <appender name="myFile" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="output.log"/><!--文件位置-->
        <param name="Append" value="true"/><!--是否選擇追加-->
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n"/>
        </layout>
    </appender>

    <!--org.apache.log4j.RollingFileAppender 滾動日誌文件輸出 文件大小到達一定尺寸時重新產生新的文件-->
    <!--<appender name="myFile" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="D:/output.log" />
        <param name="Append" value="true" />
        <param name="MaxFileSize" value="500KB"/>
        <param name="MaxBackupIndex" value="10" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
        </layout>
    </appender>-->

    <!--將各個包中的類日誌輸出到不同的日誌文件中
        這樣可以便於日誌的分類。
        可以通過這個設置,把業務邏輯的日誌添加到數據庫。起到過濾的作用
    -->
    <!--這段配置的就是說把包名爲“com.zjut.a1”且優先級爲debug的日誌通過myFile這個appender來處理。
    -->
    <category name="com.zjut.a1">
        <priority value="debug"/>
        <appender-ref ref="myFile"/>
    </category>


    <!-- 根logger的設置-->
    <root>
        <!--優先級設置,假設設置爲“info”,則無法輸出debug級別的日誌-->
        <priority value="debug"/>
        <!--<priority value="info"/>-->
        <!--<priority value="warn"/>-->
        <!--<priority value="error"/>-->
        <!--<priority value="fatal"/>-->

        <!--添加剛纔設置的appender-->
        <appender-ref ref="myConsole"/>
        <appender-ref ref="myFile"/>
    </root>
</log4j:configuration>

控制檯輸出日誌的配置文件(複製可以直接用)

<?xml version="1.0"  encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
    <appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                   value="%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n"/>
        </layout>
    </appender>
    <root>
        <priority value="debug"/>
        <appender-ref ref="myConsole"/>
    </root>
</log4j:configuration>

配置文件詳解,可以參考:http://zengxiantao.iteye.com/blog/1881700

應用調用

 // 類名.class
Logger logger = LoggerFactory.getLogger(Program.class);
// 輸出字符串
logger.debug("this is a debug msg");
// 佔位符
logger.debug("hi,welcome {},today is {}","admin","Sunday");

slf4j綁定logback的用法

pom.xml添加依賴

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>

網上教程添加了很多,其實只要添加這一個,其他的依賴jar都會被下載下來。

配置文件

配置文件幾乎和log4j差不多,如下。選擇需要的appender就可以了。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>


    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>

    <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
         the key "bySecond" into the logger context. This value will be
         available to all subsequent configuration elements. -->
    <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>testFile-${bySecond}.log</file>
        <append>true</append>
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="DAYFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logFile.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>

            <!-- keep 30 days' worth of history capped at 3GB total size -->
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>

        </rollingPolicy>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DAYFILE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

詳細配置文件,可以參考http://logback.qos.ch/manual/index.html
雖然是英文的,但是寫的已經是非常清楚了。

程序調用

同爲slf4j的api,代碼相同。

 // 類名.class
Logger logger = LoggerFactory.getLogger(Program.class);
// 輸出字符串
logger.debug("this is a debug msg");
// 佔位符
logger.debug("hi,welcome {},today is {}","admin","Sunday");

參考文獻

發佈了2 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章