Springboot 系列(四)Spring Boot 日誌框架全解析

文章已經收錄在 Github.com/niumoo/JavaNotes ,更有 Java 程序員所須要掌握的核心知識,歡迎Star和指教。
歡迎關注個人 公衆號,文章每週更新。

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

前言

Spring 框架選擇使用了 JCL 做爲默認日誌輸出。而 Spring Boot 默認選擇了 SLF4J 結合 LogBack。那咱們在項目中該使用哪一種日誌框架呢?在對於不一樣的第三方 jar 使用了不一樣的日誌框架的時候,咱們該怎麼處理呢?
<!-- more -->java

1. 日誌框架介紹

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

2. SLF4 的使用

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

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

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 以後,配置文件仍是要使用實現日誌框架的配置文件。web

3. 統一日誌框架的使用

通常狀況下,在項目中存在着各類不一樣的第三方 jar ,且它們的日誌選擇也可能不盡相同,顯然這樣是不利於咱們使用的,那麼若是咱們想爲項目設置統一的日誌框架該怎麼辦呢?面試

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

Bridging legacy APIs從圖中咱們獲得一種統一日誌框架使用的方式,可使用一種和要替換的日誌框架類徹底同樣的 jar 進行替換,這樣不至於原來的第三方 jar 報錯,而這個替換的 jar 其實使用了 SLF4J API. 這樣項目中的日誌就均可以經過 SLF4J API 結合本身選擇的框架進行日誌輸出。
統一日誌框架使用步驟概括以下shell

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

4. Spring Boot 的日誌關係

4.1. 排除其餘日誌框架

根據上面總結的要統一日誌框架的使用,第一步要排除其餘的日誌框架,在 Spring Boot 的 Maven 依賴裏能夠清楚的看到 Spring Boot 排除了其餘日誌框架。
Spring Boot 排除其餘日誌框架咱們自行排除依賴時也只須要按照圖中的方式就行了。apache

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 Maven 依賴因而可知,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 默認日誌輸出咱們能夠在 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 日誌系統

最後的話

文章已經收錄在 Github.com/niumoo/JavaNotes ,歡迎Star和指教。更有一線大廠面試點,Java程序員須要掌握的核心知識等文章,也整理了不少個人文字,歡迎 Star 和完善,但願咱們一塊兒變得優秀。

文章有幫助能夠點個「」或「分享」,都是支持,我都喜歡!
文章每週持續更新,要實時關注我更新的文章以及分享的乾貨,能夠關注「 未讀代碼 」公衆號或者個人博客

公衆號

相關文章
相關標籤/搜索