SLF4J不同的日誌實現選擇

一.使用slf4j做簡單的日誌記錄

創建基於Maven的工程,在pom.xml中添加如下內容

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.5</version>
</dependency>

現在你可以在你的Java代碼中這樣使用Logger:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloLog {

    static Logger LOGGER = LoggerFactory.getLogger(HelloLog.class);

    public static void main(String[] args) {
        
        System.out.println("log對象爲: " + LOGGER);
        System.out.println("真實對象爲: " + LOGGER.getClass());
        
        for (int i = 0; i < 10; i++)
            if (i % 2 == 0) {
                LOGGER.info("Hello {}", i);
            } else {
                LOGGER.debug("I am on index {}", i);
            }
    }
}

以上代碼可以編譯通過,但是當你運行它時,你會看到這樣的輸出:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
-------------org.slf4j.helpers.NOPLogger(NOP)
-------------class org.slf4j.helpers.NOPLogger

上面的意思是,在運行時,你沒有做日誌的實現(或者說日誌的綁定),所以slf4j簡簡單單的使用了一個什麼也不會做的空實現
爲了看到正確的輸出,你應該嘗試使用一個簡單(simple)的實現,這個實現根本不需要任何配置!只要回到pom.xml然後添加如下配置

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.5</version>
</dependency>

現在你可以在控制檯看見INFO級別的日誌輸出了。這個簡單的logger會默認顯示任何INFO或者更高級別的信息。如下:

log對象爲: org.slf4j.impl.SimpleLogger(com.study.HelloLog)
真實對象爲: class org.slf4j.impl.SimpleLogger
[main] INFO com.study.HelloLog - Hello 0
[main] INFO com.study.HelloLog - Hello 2
[main] INFO com.study.HelloLog - Hello 4
[main] INFO com.study.HelloLog - Hello 6
[main] INFO com.study.HelloLog - Hello 8

想要看DEBUG級別的信息,你需要在Java啓動時傳入這個系統屬性(system property)

-Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG

輸出結果如下:

log對象爲: org.slf4j.impl.SimpleLogger(com.study.HelloLog)
真實對象爲: class org.slf4j.impl.SimpleLogger
[main] INFO com.study.HelloLog - Hello 0
[main] DEBUG com.study.HelloLog - I am on index 1
[main] INFO com.study.HelloLog - Hello 2
[main] DEBUG com.study.HelloLog - I am on index 3
[main] INFO com.study.HelloLog - Hello 4
[main] DEBUG com.study.HelloLog - I am on index 5
[main] INFO com.study.HelloLog - Hello 6
[main] DEBUG com.study.HelloLog - I am on index 7
[main] INFO com.study.HelloLog - Hello 8
[main] DEBUG com.study.HelloLog - I am on index 9

二.使用slf4j與Log4j日誌

現在我們可以試驗並更換不同的日誌實現,但你的程序代碼可以保持不變。

我們要做的是用另一個流行的日誌實現來替換掉slf4j-simple,比如Log4j

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.5</version>
</dependency>

又一次,我們必須對我們選的每一個日誌實現做配置。在這個例子中,我們需要一個文件src/main/resources/log4j.properties

log4j.rootLogger=DEBUG, STDOUT
log4j.logger.deng=INFO
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

重運行你的程序,你會看到如下輸出結果:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/E:/OpenSources/repository/org/slf4j/slf4j-log4j12/1.7.5/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/E:/OpenSources/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
log對象爲: org.slf4j.impl.Log4jLoggerAdapter(com.study.HelloLog)
真實對象爲: class org.slf4j.impl.Log4jLoggerAdapter
 INFO [main] (HelloLog.java:22) - Hello 0
DEBUG [main] (HelloLog.java:24) - I am on index 1
 INFO [main] (HelloLog.java:22) - Hello 2
DEBUG [main] (HelloLog.java:24) - I am on index 3
 INFO [main] (HelloLog.java:22) - Hello 4
DEBUG [main] (HelloLog.java:24) - I am on index 5
 INFO [main] (HelloLog.java:22) - Hello 6
DEBUG [main] (HelloLog.java:24) - I am on index 7
 INFO [main] (HelloLog.java:22) - Hello 8
DEBUG [main] (HelloLog.java:24) - I am on index 9

從輸出日誌可以看出,slf4j找到了兩個實現,但這裏用了Log4j作爲實現,這裏有個細節要注意,當有多個實現的時候,pom文件中哪個實現寫在前面,就用哪個實現.大家可以自己調整一下位置再試一下.

三.使用slf4j和JDK日誌

JDK實際上帶有一個日誌包,你可以在pom.xml中替換爲另一個日誌實現。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.5</version>
</dependency>

現在JDK日誌的配置起來有一點困難。這裏不僅需要一個配置文件src/main/resources/logging.properties,你還需要添加一個系統屬性: -Djava.util.logging.config.file=logging.properties

這是一個logging.properties的示例:

level=INFO
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINEST
deng.level=FINEST

四.使用slf4j和Logback日誌

Logback日誌實現是一個高質量的實現。SpringBoot中默認就是採用這種日誌。還是修改你的pom.xml文件,替換成這樣

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

這是一個簡單的配置src/main/resources/logback.xml

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="deng" level="DEBUG"/>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

五.總結

如果你正在很多終端用戶(END USER)提供Java庫,那麼讓你的項目僅依賴slf4j-api絕對是個好想法,然後讓你的用戶在他們開發和運營環境中選擇任意的日誌實現。作爲終端用戶,他們可以快速地從上面提到的日誌庫中選擇一個,並且從他們自己喜歡的日誌實現的特性中受益。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章