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

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

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

slf4j log4j logback的關係

The Simple Logging Facade for Java是什麼?

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

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是衆多日誌框架中的幾種。apache

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

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

從運行結果能夠看到,因爲沒有給出具體的logger實現,沒法在控制檯輸出日誌。也就是說咱們在具體開發中,須要綁定一個日誌框架,才能正常的使用slf4j。app

log4j和logback呢?

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

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

 

上圖能夠看到應用程序對日誌框架的調用關係。應用程序調用slf4j api,而日誌的輸出最終是由底層的日誌框架來實現的。這張圖也提現了log4j和logback的不一樣。maven

官方文檔對logback的描述ide

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綁定日誌系統的優點

  1. 軟件工程的角度。抽象,解耦,便於維護。能夠參考一下上面的例子。
  2. 語法設計角度。slf4j有{}佔位符,而log4j須要用「+」來鏈接字符串,既不利於閱讀,同時消耗了內存(heap memory)。
  3. 詳細的描述能夠參考:http://www.importnew.com/7450.html
  • Logback相對log4j而言有了相對多的改進。可是二者的用法幾乎差異不大。下面是logback的優點:

    1. 更快的執行速度
    2. 充分的測試
    3. logback-classic 很是天然的實現了SLF4J
    4. 豐富的擴展文檔
    5. 可使用使用XML配置文件或者Groovy
    6. 自動從新載入配置文件
    7. 優雅地從I/O錯誤中恢復
    8. 自動清除舊的日誌歸檔文件
    9. 自動壓縮歸檔日誌文件
    10. 更多優勢能夠參考官方文檔。中文版英文版

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

  • slf4j綁定log4j的用法

    因爲如今log4j使用的還比較多,因此介紹下他的基本用法。

    ide相關設置

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

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

        

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

      配置文件

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

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

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

      3.     FATAL        
            ERROR      
            WARN        
            INFO        
            DEBUG  

        下面給出配置文件。

      4. <?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>

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

      5. <?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添加依賴

      6. <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,代碼相同。

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

         

        參考文獻

相關文章
相關標籤/搜索