SLF4J 日誌門面

北涯 發表於 2022-07-03

01、簡單介紹

官方網址:https://www.slf4j.org/

SLF4J( Simple Logging Facade For Java),即 簡單日誌門面。主要是為了給 Java 日誌訪問提供一套標準、規範的 API 框架,其主要意義在於提供介面,具體的實現可以交由其他日誌框架,例如 Log4j 或 Logback 等。

SLF4J 自身也提供了功能較為簡單的實現,但是一般很少用到。對於一般的 Java 專案而言,日誌框架會選擇 slf4j-api 作為門面,配上具體的實現框架,中間使用橋接器完成橋接。所以 SLF4J 最重要的兩個功能就是對於日誌框架的繫結以及日誌框架的橋接。

02、日誌級別

級別 描述
trace 日誌追蹤資訊
debug 日誌詳細資訊
info(預設) 日誌關鍵資訊
warn 日誌警告資訊
error 日誌錯誤資訊

03、入門案例

匯入依賴:

<dependencies>
    <!-- slf4j核心依賴 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <!-- slf4j自帶的簡單日誌實現 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.25</version>
    </dependency>
    <!-- 單元測試 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

程式碼示例:

package com.slf4j;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jTest {
    @Test
    public void test01(){
        // 沒有整合其它日誌實現框架的話,使用自帶的簡單日誌實現框架(slf4j-simple)
        Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
        logger.trace("trace追蹤資訊");
        logger.debug("debug詳細資訊");
        logger.info("info關鍵資訊");
        logger.warn("warn警告資訊");
        logger.error("error錯誤資訊");
    }
}

執行結果:

[main] INFO com.slf4j.Slf4jTest - info關鍵資訊
[main] WARN com.slf4j.Slf4jTest - warn警告資訊
[main] ERROR com.slf4j.Slf4jTest - error錯誤資訊

03、動態列印

程式碼示例:

@Test
public void test02() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    String name = "張三";
    int age = 23;
    // 字串拼接,麻煩、可讀性差
    //logger.info("學生資訊:姓名-" + name + ";年齡-" + age + "");
    // 動態資訊列印,使用佔位符的形式來代替字串的拼接
    logger.info("學生資訊:姓名-{};年齡-{}", name, age);
}

執行結果:

[main] INFO com.slf4j.Slf4jTest - 學生資訊:姓名-張三;年齡-23

04、異常列印

程式碼示例:

@Test
public void test03() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    try {
        Class.forName("User");
    } catch (ClassNotFoundException e) {
        logger.info("異常資訊:", e);
    }
}

執行結果:

[main] INFO com.slf4j.Slf4jTest - 異常資訊:
java.lang.ClassNotFoundException: User
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at com.slf4j.Slf4jTest.test03(Slf4jTest.java:34)
    ...

05、日誌整合

SLF4J 日誌門面共有三種情況對日誌實現進行繫結。

  • 在沒有繫結任何日誌實現框架的基礎上,日誌不能實現任何功能。slf4j-simple 是 SLF4J 官方提供的簡單實現,也需要匯入依賴,自動繫結到 SLF4J 日誌門面上。

  • Logback 和 Simple(包括 nop) 是 SLF4 出現後提供的日誌實現框架,所以 API 完全遵循 SLF4J 進行設計。只需要匯入對應的日誌實現依賴,即可與 SLF4J 無縫銜接。nop 雖然也劃分到實現中,但它是指不實現日誌記錄。

  • Log4j 和 JUL 是 SLF4J 出現前就已經存在的日誌實現框架,所以 API 不遵循 SLF4J 進行設計。需要通過適配橋接的技術,完成的與 SLF4J 的銜接。

注意: 在 SLF4J 環境下,若同時匯入多個日誌實現框架,預設使用先匯入的。在實際應用中,一般只整合一種日誌實現。

06、整合 logback

匯入依賴: 註釋 slf4j-simple 依賴。

<!-- logback日誌框架 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

程式碼示例:

@Test
public void test01() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    logger.trace("trace追蹤資訊");
    logger.debug("debug詳細資訊");
    logger.info("info關鍵資訊");
    logger.warn("warn警告資訊");
    logger.error("error錯誤資訊");
}

執行結果:

12:26:18.489 [main] DEBUG com.slf4j.Slf4jTest - debug詳細資訊
12:26:18.492 [main] INFO com.slf4j.Slf4jTest - info關鍵資訊
12:26:18.492 [main] WARN com.slf4j.Slf4jTest - warn警告資訊
12:26:18.492 [main] ERROR com.slf4j.Slf4jTest - error錯誤資訊

07、整合 slf4j-nop

匯入依賴: 註釋 logback 依賴。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>1.7.25</version>
</dependency>

程式碼示例:

@Test
public void test01() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    logger.trace("trace追蹤資訊");
    logger.debug("debug詳細資訊");
    logger.info("info關鍵資訊");
    logger.warn("warn警告資訊");
    logger.error("error錯誤資訊");
}

執行結果: 可以看到沒有日誌輸出,其主要作用是禁止日誌列印。


08、整合 log4j

匯入依賴: 註釋 slf4j-nop 依賴。

<!-- log4j日誌框架 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

程式碼示例:

@Test
public void test01() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    logger.trace("trace追蹤資訊");
    logger.debug("debug詳細資訊");
    logger.info("info關鍵資訊");
    logger.warn("warn警告資訊");
    logger.error("error錯誤資訊");
}

執行結果: 報錯了。

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.

因為 Log4j 是 SLF4J 出現前就已經存在的日誌實現框架,所以 API 不遵循 SLF4J 進行設計。需要通過適配橋接的技術來完成的與 SLF4J 的銜接。

匯入依賴:

<!-- log4j介面卡 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

再次執行: 雖然日誌資訊沒有列印出來,但根據警告資訊可看出使用了 Log4j 日誌框架。

log4j:WARN No appenders could be found for logger (com.slf4j.Slf4jTest).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

建立配置: log4j.properties 檔案。

#配置日誌級別,輸出器
log4j.rootLogger=INFO,console
#配置控制檯輸出器
log4j.appender.console=org.apache.log4j.ConsoleAppender
#配置自定義格式器
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#配置自定義轉換模式
log4j.appender.console.layout.conversionPattern=[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5p] [%t] [%-4rms] [%c#%M-%L] %m%n

再次執行:

[2022-07-01 12:44:21.977] [INFO ] [main] [0   ms] [com.slf4j.Slf4jTest#test01-14] info關鍵資訊
[2022-07-01 12:44:21.979] [WARN ] [main] [2   ms] [com.slf4j.Slf4jTest#test01-15] warn警告資訊
[2022-07-01 12:44:21.979] [ERROR] [main] [2   ms] [com.slf4j.Slf4jTest#test01-16] error錯誤資訊

09、整合 jul

因為 JUL 日誌框架是 JDK 內建的工具包,無需匯入依賴。JUL 是 SLF4J 出現前就已經存在的日誌實現框架,所以 API 不遵循 SLF4J 進行設計。需要通過適配橋接的技術,完成的與 SLF4J 的銜接。

匯入依賴:

<!-- jul介面卡 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.25</version>
</dependency>

程式碼示例:

@Test
public void test01() {
    Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    logger.trace("trace追蹤資訊");
    logger.debug("debug詳細資訊");
    logger.info("info關鍵資訊");
    logger.warn("warn警告資訊");
    logger.error("error錯誤資訊");
}

執行結果:

七月 01, 2022 12:50:56 下午 com.slf4j.Slf4jTest test01
資訊: info關鍵資訊
七月 01, 2022 12:50:56 下午 com.slf4j.Slf4jTest test01
警告: warn警告資訊
七月 01, 2022 12:50:56 下午 com.slf4j.Slf4jTest test01
嚴重: error錯誤資訊