清晰梳理最全日誌框架關係與日誌配置-SpringBoot 2.7.2 實戰基礎

来源:https://www.cnblogs.com/youyacoder/archive/2022/08/15/16588510.html
-Advertisement-
Play Games

Java 中日誌相關的 jar 包非常多,log4j、log4j2、commons-logging、logback、slf4j 等,本文首先梳理這些包之間關係,然後介紹在 spring boot 中日誌的配置,最後介紹多環境的配置。 ...


優雅哥 SpringBoot 2.7.2 實戰基礎 - 07 - 日誌配置

Java 中日誌相關的 jar 包非常多,log4j、log4j2、commons-logging、logback、slf4j 等,本文首先梳理這些包之間關係,然後介紹在 spring boot 中日誌的配置,最後介紹多環境的配置。

1 日誌框架歷史

image-20220730230157396

1.1 log4j

很多年前,一個叫 Ceki Gülcü 的大佬在一個項目中開發跟蹤 API,這套跟蹤 API 逐步演變成 log4j, 大概1999年,log4j 成為 Apache 的一員。

1.2 JUL

JUL:java.util.logging.

Apache 覺得 log4j 很有價值,就推薦給 SUN 公司(Java 語言是由 SUN 公司的 James Gosling 發明的),希望 SUN 公司在 JDK 中加入 log4j,SUN 公司覺得加入日誌 API 很有必要,但是又看不上 log4j,於是便自己搞了一套官方的,於 2002 年 JDK 1.4 中實現了 JUL

此時,市面上就有兩套日誌 API:來自 Apache 的 log4j 和來自官方的 JUL

1.3 JCL(Jakarta Commons Logging)和 Simple Log

JCL:Jakarta Commons Logging.

log4jJUL 是兩套不同的 API。一個出現較早、一個是官方的,兩個用戶群體都較大。如果在項目中想要切換日誌框架就需要改動大量代碼,同時這也不符合”面向介面編程“的設計原則。Apache 就推出了 JCL 項目,名字看著高大上,但這玩意兒就是在 SSH、SSM 時代到處都能看見,那就是搭建框架時經常會看到的 commons-logging 包,該項目是一套日誌的抽象層(後來大神們針對這種日誌的抽象層一個高端的名字——日誌門面)。所謂”抽象層“,本質上就是一堆介面,有介面就需要有實現,沒有實現那就是自娛自樂,沒有鳥用。所以 Apache 針對 JCL 提供了一個預設實現,那就是 Simple Log

JCL 基於動態綁定來實現日誌的記錄:開發過程中使用 JCL 定義的介面,程式運行的時候使用類路徑 classpath 中的具體實現(Simple Log、log4j、JUL)。

可以和 JDBC 類比,Java 官方制定了資料庫訪問層持久化操作的標準 JDBC,各個資料庫廠商(Oracle、MySQL等)實現這套標準。JCL 也是想成為規範制定者,統一日誌操作的規範。

JCL 的出現,日誌體系顯得比較優雅,面向 JCL 的介面編程,可以很方便的切換日誌框架。在這個時候, log4j他爹 Ceki`因為一些未知的原因離開了 Apache。

1.4 slf4j

slf4j:Simple Logging Facade for Java.

寫代碼的人大多有個共性:別人寫的都是垃圾、自己昨天寫的代碼也是垃圾,只有自己現在寫的才是最好的。Ceki 這哥們同樣覺得 JCL 不是特別完美,於是自己又搞了一套新版本的日誌介面(高端的名字是:日誌門面):slf4j。

問題來了,slf4j 只有介面沒有實現,難不成要讓 log4j 和 JUL 都來實現 slf4j 嗎?肯定是不可能的。

JCL 是採用動態綁定機制,而 slf4j 採用”橋接包“,也就是分別開發 log4j 和 JUL 的橋接包,通過橋接包來適配兩者。大牛就是大牛,Ceki提供了這些橋接包 slf4j-log4jslf4j-jdk14等。由於 JCL 出現比 slf4j 早,很多項目使用了 JCL,所以這大佬也提供了 slf4j-jcl

還有一種常見:在某個項目中使用了一個第三方框架,這個項目使用了 slf4j 和 log4j,而依賴的第三方框架使用了 JCL 和 JUL,這時候系統就會有兩種日誌配置文件和兩種列印方式,亂七八糟的。 Ceki Gülcü 也考慮到這種場景,沒有他的橋接包搞不定的場景,於是就弄了個 jcl-over-slf4j 的橋接包...

1.5 logback

Ceki Gülcü 弄了 slf4j 和一堆橋接包,2006 年為 slf4j 提供了一個很厲害的實現:logback。與此同時他還特意寫了一篇文章《Reasons to prefer logback over log4j》。畢竟 log4j 也出自於他的手,裡面存在什麼問題他最清楚。事實上,logback 的性能和設計確實比 log4j 更厲害,與時俱進嘛。

1.6 log4j2

logback 的出現讓 Apache 坐不住了,2012年推出了新項目 log4j2。看名字像是 log4j的升級版,實際上是一個全新的玩意,它不相容log4j。log4j2 幾乎包括了 logback的特性。競爭是殘酷的,與slf4j類似,log4j2也想統一日誌的天下,也弄了一堆橋接包,通過橋接包 log4j-xxx 去相容上面各種各樣的日誌框架...

亂七八糟扯了一堆,核心就三個概念:

  1. 日誌門面:JCL、slf4j

  2. 日誌產品:log4j、JUL、logback、log4j2

  3. 橋接包:slf4j-xxx、log4j-xxx

2 Spring Boot 日誌配置

Spring Boot 底層預設使用 slf4j 和 logback 的方式記錄日誌。咱們 demo 工程中依賴了 spring-boot-starter-web,它又依賴了 spring-boot-starter-logging,所以不需要再手動添加該依賴。

在 Spring Boot 中,application.yml 支持部分 logback 的日誌配置,但一些高級配置只能通過獨立的 xml 配置文件實現,經過 Spring Boot 的整合後,可支持多環境配置,但 logback 配置文件需要命名為 logback-spring.xml。如果使用了自定義日誌配置文件,application.yml中 logging 有關配置就會失效。

2.1 springboot 預設的 logback 配置

SpringBoot 預設提供了一套 logback 的配置文件,位於 spring-boot依賴中的 org/springframework/boot/logging/logback/base.xml

image-20220803152358664

該文件引入了三個 xml 文件,並設置了root的日誌級別為 info。console-appender.xml 和 file-appender.xml 中定義了日誌的追加器,分別是名為 CONSOLE 的控制台追加器 和 名為 FILE 的文件追加器。

org/springframework/boot/logging/logback/defaults.xml 定義了 logback 的轉換器、一些包的日誌級別、日誌顯示格式。

image-20220803152134192

預設在控制臺中顯示彩色日誌,就是因為使用了轉換器 ColorConverter,顯示的格式為 CONSOLE_LOG_PATTERN 中使用了該轉換器。

在我們的自定義配置中可以復用這個 default.xml 和 console-appender.xml。

2.2 自定義配置

src/main/resources/下創建配置文件 logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />

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

上面的配置引入了 spring boot 中 logback 的預設配置和 CONSOLE 追加器,並定義了 root 的日誌級別為 info。

2.3 日誌級別

日誌有五個級別:trace、debug、info、warn、error,級別依次較高,配置了某個級別,就會輸出該級別及其以上的級別。如,配置日誌級別為 warn,則日誌會輸出 warn、error;如果配置日誌級別為 debug,則會輸出 debug、info、warn、error。

DemoControllerhello 方法中添加日誌輸出,測試日誌級別:

@RestController
@RequestMapping("demo")
public class DemoController {

    private Logger logger = LoggerFactory.getLogger(DemoController.class);

    @GetMapping("hello")
    public String hello(String msg) {
        String result = "Hello Spring Boot ! " + msg;
        System.out.println(result);
        logger.error("error log");
        logger.warn("warn log");
        logger.info("info log");
        logger.debug("debug log");
        logger.trace("trace log");
        return result;
    }
}

註意,引入的 Logger 和 LoggerFactory 兩個類都是 slf4j 包下麵的。上面的代碼分別輸出五個級別的日誌。啟動服務,訪問 hello 介面,控制台輸出:

image-20220803143050714

控制台值輸出 info、warn、error,可以看出 SpringBoot 預設輸出級別為 info。可通過配置細粒度調整日誌的級別:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    ...
    <logger name="com.yygnb.demo" level="trace"/>
  	...
</configuration>

上面按照包名更改了日誌的顯示級別,com.yygnb.demo 包下麵的日誌都是 trace 級別。重新訪問 hello 介面,error、warn、info、debug、trace 都會全部列印出來。

如果使用了 lombok,可以不用手動創建 logger 對象,使用註解 @Slf4j 後,就能直接在代碼中使用 log 對象:

@Slf4j
@RestController
@RequestMapping("demo")
public class DemoController {

    @GetMapping("hello")
    public String hello(String msg) {
        String result = "Hello Spring Boot ! " + msg;
        System.out.println(result);
        log.error("error log");
        log.warn("warn log");
        log.info("info log");
        log.debug("debug log");
        log.trace("trace log");
        return result;
    }
}

關於是否應該使用 lombok,網上各種義正言辭、牽強附會的說辭都有,甚至有些標題黨寫著《我們公司的技術總監規定xxxx》,我只能說遵守公司或項目規定就行。

2.4 文件追加器

上面復用了 SpringBoot 自帶的控制台追加器 CONSOLE,這裡自定義文件追加器:

...
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>INFO</level>
    </filter>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>logs/hero-springboot-demo.%d.log</fileNamePattern>
        <MaxHistory>100</MaxHistory>
    </rollingPolicy>
</appender>
...

併在 root 中添加這個自定義 FILE 追加器:

<root level="INFO">
    <appender-ref ref="CONSOLE" />
    <appender-ref ref="FILE" />
</root>

上面的 FILE 追加器,日誌路徑為項目根路徑下的 logs 目錄,日誌名稱形如 hero-springboot-demo.2022-08-02.log。啟動服務,訪問 hello 介面,測試日誌文件是否生成。

2.5 多環境日誌

假設希望在 local 時,只輸出控制台日誌;在其他環境(dev、test等)輸出控制台日誌和文件日誌。SpringBoot 提供了 springProfile 標簽,通過該元素 name 屬性指定環境。修改 root 元素:

<root level="INFO">
    <springProfile name="local">
        <appender-ref ref="CONSOLE" />
    </springProfile>
    <springProfile name="!local">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </springProfile>
</root>

分別使用 local 和 dev 啟動服務,測試多環境是否生效。

我們自定義的 logback-spring.xml 充分利用了 Spring Boot 官方提供的配置,最終完整配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />

    <logger name="com.yygnb.demo" level="trace"/>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/hero-springboot-demo.%d.log</fileNamePattern>
            <MaxHistory>100</MaxHistory>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <springProfile name="local">
            <appender-ref ref="CONSOLE" />
        </springProfile>
        <springProfile name="!local">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE" />
        </springProfile>
    </root>
</configuration>

image

/ 程式員優雅哥(youyacoder),今日學習到此結束~~~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.簡介: 本文將完成一個真實業務中的設備上報數據的一個例子,完整的展示後臺服務接收到設備上報的數據後,將數據添加到時序資料庫,並且將數據查詢出來的一個例子。本文所有代碼已經上傳GitHub:https://github.com/Tom-shushu/work-study 下的 iotdb-demo ...
  • 文件的創建: package file; import java.io.File; import java.io.IOException; /* create:創建 new:新 file:文件 使用File新建一個文件 / public class CreateNewFileDemo { publi ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • Python爬蟲之xpath語法及案例使用 鋼鐵俠的知識庫 2022.08.15 我們在寫Python爬蟲時,經常需要對網頁提取信息,如果用傳統正則表達去寫會增加很多工作量,此時需要一種對數據解析的方法,也就是本章要介紹的Xpath表達式。 Xpath是什麼 XPath,全稱 XML Path La ...
  • Java集合04 9.Set介面方法 Set介面基本介紹 無序(添加和取出的順序不一致),沒有索引 不允許重覆元素,所以最多只有一個null JDK API中介面的實現類有: Set介面的常用方法:和List介面一樣,Set介面也是Collection的子介面,因此,常用方法和Collection接 ...
  • 4、Fixture的相互調用 示例: import pytest # 第一層fixture @pytest.fixture() def fixture_1(): data = "fixture_1" print("這是第一層fixture") return data # 第二層fixture @py ...
  • 前言 嗨嘍~大家好呀,這裡是魔王吶 ! 在這平凡的一日,我決定~ 乾一件平凡的事~讓我們開動起我們的小手 來做一個小小的顏值檢測叭~ 開發環境: Python 3.8 Pycharm 2021.2 模塊使用: requests >>> pip install requests tqdm >>> pi ...
  • 1、BaseDao 持久層業務介面實現類的公共父類,定義了jdbc操作資料庫的所有公共方法,方便子類繼承; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import ja ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...