Springboot 系列(四)Spring Boot 日志框架


注意:本 Spring Boot 系列文章基於 Spring Boot 版本 v2.1.1.RELEASE 進行學習分析,版本不同可能會有細微差別。

前言

Spring 框架選擇使用了 JCL 作為默認日志輸出。而 Spring Boot 默認選擇了 SLF4J 結合 LogBack。那我們在項目中該使用哪種日志框架呢?在對於不同的第三方 jar 使用了不同的日志框架的時候,我們該怎么處理呢?

1. 日志框架介紹

日志對於應用程序的重要性不言而喻,不管是記錄運行情況還是追蹤線上問題,都離不開對日志的分析,在 Java 領域里存在着多種日志框架,如 JUL, Log4j, Log4j2, Commons Loggin, Slf4j, Logback 等。關於 Log4j, Log4j2 和 Slf4j 直接的故事這里不做介紹,有興趣可以自行百度。

2. SLF4 的使用

在開發的時候不應該直接使用日志實現類,應該使用日志的抽象層。具體參考 SLF4J 官方
下圖是 SLF4J 結合各種日志框架的官方示例,從圖中可以清晰的看出 SLF4J API 永遠作為日志的門面,直接應用與應用程序中。

同時 SLF4 官方給出了簡單示例。

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

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

需要注意的是,要為系統導入 SLF4J 的 jar 和 日志框架的實現 jar. 由於每一個日志的實現框架都有自己的配置文件,所以在使用 SLF4 之后,配置文件還是要使用實現日志框架的配置文件。

3. 統一日志框架的使用

一般情況下,在項目中存在着各種不同的第三方 jar ,且它們的日志選擇也可能不盡相同,顯然這樣是不利於我們使用的,那么如果我們想為項目設置統一的日志框架該怎么辦呢?

SLF4J 官方,也給了我們參考的例子。

從圖中我們得到一種統一日志框架使用的方式,可以使用一種和要替換的日志框架類完全一樣的 jar 進行替換,這樣不至於原來的第三方 jar 報錯,而這個替換的 jar 其實使用了 SLF4J API. 這樣項目中的日志就都可以通過 SLF4J API 結合自己選擇的框架進行日志輸出。
統一日志框架使用步驟歸納如下

  1. 排除系統中的其他日志框架。
  2. 使用中間包替換要替換的日志框架。
  3. 導入我們選擇的 SLF4J 實現。

4. Spring Boot 的日志關系

4.1. 排除其他日志框架

根據上面總結的要統一日志框架的使用,第一步要排除其他的日志框架,在 Spring Boot 的 Maven 依賴里可以清楚的看到 Spring Boot 排除了其他日志框架。


我們自行排除依賴時也只需要按照圖中的方式就好了。

4.2. 統一框架引入替換包

其實 Spring Boot 也是使用了 SLF4J+logback 的日志框架組合,查看 Spring Boot 項目的 Maven 依賴關系可以看到 Spring Boot 的核心啟動器 spring-boot-starter 引入了 spring-boot-starter-logging.

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>2.1.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>

而 spring-boot-starter-logging 的 Maven 依賴主要引入了 logback-classic (包含了日志框架 Logback 的實現),log4j-to-slf4j (在 log4j 日志框架作者開發此框架的時候還沒有想到使用日志抽象層進行開發,因此出現了 log4j 向 slf4j 轉換的工具),jul-to-slf4j ( Java 自帶的日志框架轉換為 slf4j).

  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-to-slf4j</artifactId>
      <version>2.11.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jul-to-slf4j</artifactId>
      <version>1.7.25</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

從上面的分析,Spring Boot 對日志框架的使用已經是清晰明了了,我們使用 IDEA 工具查看 Maven 依賴關系,可以清晰的看到日志框架的引用。如果沒有 IDEA 工具,也可以使用 Maven 命令查看依賴關系。

mvn dependency:tree

由此可見,Spring Boot 可以自動的適配日志框架,而且底層使用 SLF4 + LogBack 記錄日志,如果我們自行引入其他框架,需要排除其日志框架。

5. Spring Boot 的日志使用

5.1. 日志級別和格式

從上面的分析,發現 Spring Boot 默認已經使用了 SLF4J + LogBack . 所以我們在不進行任何額外操作的情況下就可以使用 SLF4J + Logback 進行日志輸出。
編寫 Java 測試類進行測試。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * <p>
 * 測試日志輸出,
 * SLF4J 日志級別從小到大trace,debug,info,warn,error
 *
 * @Author niujinpeng
 * @Date 2018/12/11 21:12
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class LogbackTest {
    
    Logger logger = LoggerFactory.getLogger(getClass());

    @Test
    public void testLog() {
        logger.trace("Trace 日志...");
        logger.debug("Debug 日志...");
        logger.info("Info 日志...");
        logger.warn("Warn 日志...");
        logger.error("Error 日志...");
    }
}

已知日志級別從小到大為 trace < debug < info < warn < error . 運行得到輸出如下。由此可見 Spring Boot 默認日志級別為 INFO.

2018-12-11 23:02:58.028 [main] INFO  n.c.boot.LogbackTest - Info 日志...
2018-12-11 23:02:58.029 [main] WARN  n.c.boot.LogbackTest - Warn 日志...
2018-12-11 23:02:58.029 [main] ERROR n.c.boot.LogbackTest - Error 日志...

從上面的日志結合 Logback 日志格式可以知道 Spring Boot 默認日志格式是。

%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# %d{yyyy-MM-dd HH:mm:ss.SSS} 時間
# %thread 線程名稱
# %-5level 日志級別從左顯示5個字符寬度
# %logger{50} 類名
# %msg%n 日志信息加換行

至於為什么 Spring Boot 的默認日志輸出格式是這樣?

我們可以在 Spring Boot 的源碼里找到答案。

5.2 自定義日志輸出

可以直接在配置文件編寫日志相關配置。

# 日志配置
# 指定具體包的日志級別
logging.level.net.codingme=debug
# 控制台和日志文件輸出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# 日志文件大小
logging.file.max-size=10MB
# 保留的日志時間
logging.file.max-history=10
# 日志輸出路徑,默認文件spring.log
logging.path=systemlog
#logging.file=log.log

關於日志的輸出路徑,可以使用 logging.file 或者 logging.path 進行定義,兩者存在關系如下表。

logging.file logging.path 例子 描述
(沒有) (沒有) 僅控制台記錄。
具體文件 (沒有) my.log 寫入指定的日志文件,名稱可以是精確位置或相對於當前目錄。
(沒有) 具體目錄 /var/log 寫入spring.log指定的目錄,名稱可以是精確位置或相對於當前目錄。

6. 替換日志框架

因為 Log4j 日志框架已經年久失修,原作者都覺得寫的不好,所以下面演示替換日志框架為 Log4j2 的方式。根據官網我們 Log4j2 與 logging 需要二選一,因此修改 pom如下。

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

文章代碼已經上傳到 GitHub Spring Boot 日志系統

<完>
本文原發於個人博客:https://www.codingme.net 轉載請注明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM