SpringBoot整合日志功能(slf4j+logback)詳解(最新推薦)
一、日志門(mén)面與日志實(shí)現(xiàn)
1.1 什么是日志門(mén)面和日志實(shí)現(xiàn)?

日志門(mén)面相當(dāng)于JDBC接口,而日志實(shí)現(xiàn)類(lèi)似于Mysql、Oracle、SqlServer等。
在Java生態(tài)體系中,圍繞著日志,有很多成熟的解決方案。關(guān)于日志輸出,主要有兩類(lèi)工具。
一類(lèi)是日志框架(Log4j、Logback),主要用來(lái)進(jìn)行日志的輸出的,比如輸出到哪個(gè)文件,日志格式如何等。另 外一類(lèi)是日志門(mén)面(slf4j,commons-logging),主要一套通用的API,用來(lái)屏蔽各個(gè)日志框架之間的差異的。
對(duì)于Java工程師來(lái)說(shuō),關(guān)于日志工具的使用,最佳實(shí)踐就是在應(yīng)用中使用如Log4j + SLF4J這樣的組合來(lái)進(jìn)行日志 輸出。
這樣做的最大好處,就是業(yè)務(wù)層的開(kāi)發(fā)不需要關(guān)心底層日志框架的實(shí)現(xiàn)及細(xì)節(jié),在編碼的時(shí)候也不需要考慮日后更 換框架所帶來(lái)的成本。這也是門(mén)面模式所帶來(lái)的好處。
1.2 為什么需要日志門(mén)面?
前面提到過(guò)一個(gè)重要的原因,就是為了在應(yīng)用中屏蔽掉底層日志框架的具體實(shí)現(xiàn)。這樣的話,即使有一天要更換代 碼的日志框架,只需要修改jar包,最多再改改日志輸出相關(guān)的配置文件就可以了。這就是解除了應(yīng)用和日志框架 之間的耦合。
有人或許會(huì)問(wèn)了,如果我換了日志框架了,應(yīng)用是不是就改了,那日志門(mén)面不還是需要改的嗎?
要回答這個(gè)問(wèn)題,我們先來(lái)舉一個(gè)例子,再把門(mén)面模式碎了重新解釋一遍。
日志門(mén)面就像飯店的服務(wù)員,而日志框架就像是后廚的廚師。對(duì)于顧客這個(gè)應(yīng)用來(lái)說(shuō),我到飯店點(diǎn)菜,我只需要告 訴服務(wù)員我要一盤(pán)番茄炒雞蛋即可,我不關(guān)心他后廚的所有事情。因?yàn)殡m然主廚從把這道菜稱之為「番茄炒蛋」的廚師 換成了把這道菜稱之為「西紅柿炒雞蛋」的廚師。但是,顧客不需要關(guān)心,他只要下達(dá)「番茄炒蛋」的命令給到 服務(wù)員,由服務(wù)員再去翻譯給廚師就可以了。
所以,對(duì)于一個(gè)了解了「番茄炒蛋」的多種叫法的服務(wù)員來(lái)說(shuō),無(wú)論后廚如何換廚師,他都能準(zhǔn)確的幫用戶下單。
同理,對(duì)于一個(gè)設(shè)計(jì)的全面、完善的日志門(mén)面來(lái)說(shuō),他也應(yīng)該是無(wú)縫兼容了多種日志框架的。所以,底層框架的 更換,日志門(mén)面幾乎不需要改動(dòng)。
以上,就是日志門(mén)面的一個(gè)比較重要的好處——解耦。
二、簡(jiǎn)介
- Spring使用commons-logging作為內(nèi)部日志,但底層日志實(shí)現(xiàn)是開(kāi)放的??蓪?duì)接其他日志框架。spring5及以后 commons-logging被spring直接自己寫(xiě)了。
- 支持 jul,log4j2,logback。SpringBoot 提供了默認(rèn)的控制臺(tái)輸出配置,也可以配置輸出為文件。
- logback是默認(rèn)使用的。
- 雖然日志框架很多,但是我們不用擔(dān)心,使用 SpringBoot 的默認(rèn)配置就能工作的很好。
SpringBoot怎么把日志默認(rèn)配置好的?
- 每個(gè)
starter場(chǎng)景,都會(huì)導(dǎo)入一個(gè)核心場(chǎng)景spring-boot-starter - 核心場(chǎng)景引入了日志的所用功能
spring-boot-starter-logging - 默認(rèn)使用了
slf4j + logback組合作為默認(rèn)底層日志 日志是系統(tǒng)一啟動(dòng)就要用,而xxxAutoConfiguration是系統(tǒng)啟動(dòng)好了以后放好的組件,后來(lái)用的。- 日志是利用監(jiān)聽(tīng)器機(jī)制配置好的。
ApplicationListener。 - 日志所有的配置都可以通過(guò)修改配置文件實(shí)現(xiàn)。以
logging開(kāi)始的所有配置。
三、日志格式
2023-03-31T13:56:17.511+08:00 INFO 4944 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-03-31T13:56:17.511+08:00 INFO 4944 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.7]
默認(rèn)輸出格式:
- 時(shí)間和日期:毫秒級(jí)精度
- 日志級(jí)別:ERROR, WARN, INFO, DEBUG, or TRACE.
- 進(jìn)程 ID
- ---: 消息分割符
- 線程名: 使用[]包含
- Logger 名: 通常是產(chǎn)生日志的類(lèi)名
- 消息: 日志記錄的內(nèi)容
注意: logback 沒(méi)有FATAL級(jí)別,對(duì)應(yīng)的是ERROR
默認(rèn)值:參照:spring-boot包additional-spring-configuration-metadata.json文件
默認(rèn)輸出格式值:%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
在application.properties可修改為:
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} ===> %msg%n啟動(dòng)項(xiàng)目發(fā)現(xiàn)日志變成我們修改的樣子了。

四、記錄日志
4.1 使用日志工廠
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
Logger log = LoggerFactory.getLogger(getClass());
@GetMapping("/hello")
public String hello(){
log.info("方法進(jìn)來(lái)了...");
return "Hello,Spring Boot 3!";
}
}
4.2 使用Lombok的@Slf4j注解
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
log.info("方法進(jìn)來(lái)了...");
return "Hello,Spring Boot 3!";
}
}五、日志級(jí)別
5.1 日志級(jí)別介紹
- 由低到高:ALL,TRACE, DEBUG, INFO, WARN, ERROR,FATAL,OFF;
- 只會(huì)打印指定級(jí)別及以上級(jí)別的日志
- ALL:打印所有日志
- TRACE:追蹤框架詳細(xì)流程日志,一般不使用
- DEBUG:開(kāi)發(fā)調(diào)試細(xì)節(jié)日志
- INFO:關(guān)鍵、感興趣信息日志
- WARN:警告但不是錯(cuò)誤的信息日志,比如:版本過(guò)時(shí)
- ERROR:業(yè)務(wù)錯(cuò)誤日志,比如出現(xiàn)各種異常
- FATAL:致命錯(cuò)誤日志,比如jvm系統(tǒng)崩潰
- OFF:關(guān)閉所有日志記錄
- 不指定級(jí)別的所有類(lèi),都使用root指定的級(jí)別作為默認(rèn)級(jí)別
- SpringBoot日志默認(rèn)級(jí)別是 INFO
也就是說(shuō),如果你配置文件沒(méi)有配置日志級(jí)別,那么默認(rèn)級(jí)別是info,打印的也是info順序后面的日志級(jí)別,包括info、warn、error、fatal、off等。
5.2 配置日志級(jí)別
application.properties中配置:
logging.level.root = debug
這樣配置代表以后debug及以后級(jí)別的日志都可以打印。
5.3 指定某個(gè)包下的類(lèi)使用某個(gè)級(jí)別
logging.level.com.atguigu.controller=debug
代表只有com.atguigu.controller包使用debug級(jí)別,其余都使用默認(rèn)info級(jí)別。
5.4 占位符打印
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(String a, String b){
log.info("info日志:參數(shù)a:{} 參數(shù)b:{}", a, b);
return "Hello,Spring Boot 3!";
}
}
六、日志分組
有這么一種場(chǎng)景,比如我的包很多,這些包都想設(shè)置debug級(jí)別,那么配置如下:
logging.level.com.atguigu.controller=debug
logging.level.com.atguigu.service=debug
logging.level.com.atguigu.dao=debug
logging.level.com.atguigu.entity=debug
logging.level.com.atguigu.common=debug
...
這樣當(dāng)包有很多的時(shí)候,寫(xiě)起來(lái)很麻煩?。?!那么有什么辦法呢?沒(méi)錯(cuò),就是分組。
比如我把這些包分成一個(gè)組,組名叫abc,配置如下:
logging.group.abc=com.atguigu.controller,com.atguigu.service,com.atguigu.dao,com.atguigu.entity,com.atguigu.common
logging.level.abc=debug
這樣不就簡(jiǎn)便很多了嗎?
七、文件輸出
SpringBoot 默認(rèn)只把日志寫(xiě)在控制臺(tái),如果想額外記錄到文件,可以在application.properties中添加logging.file.name or logging.file.path配置項(xiàng)。
logging.file.name | logging.file.path | 示例 | 效果 |
未指定 | 未指定 | 僅控制臺(tái)輸出 | |
指定 | 未指定 | my.log | 寫(xiě)入指定文件??梢约勇窂?/p> |
未指定 | 指定 | /var/log | 寫(xiě)入指定目錄,文件名為spring.log |
指定 | 指定 | 以logging.file.name為準(zhǔn) |
例:將日志打印在D盤(pán)的/logs/my.log中
logging.file.name=D:/logs/my.log

八、文件歸檔與滾動(dòng)切割
比如我們將項(xiàng)目的日志打印到D:\\my.log中,那么時(shí)間短還行,如果持續(xù)一年,我們的日志文件將會(huì)非常大,打開(kāi)都會(huì)崩的狀態(tài)。
歸檔:每天的日志單獨(dú)存到一個(gè)文檔中。
切割:每個(gè)文件10MB,超過(guò)大小切割成另外一個(gè)文件。
- 每天的日志應(yīng)該獨(dú)立分割出來(lái)存檔。如果使用logback(SpringBoot 默認(rèn)整合),可以通過(guò)application.properties/yaml文件指定日志滾動(dòng)規(guī)則。
- 如果是其他日志系統(tǒng),需要自行配置(添加log4j2.xml或log4j2-spring.xml)
- 支持的滾動(dòng)規(guī)則設(shè)置如下
配置項(xiàng) | 描述 |
logging.logback.rollingpolicy.file-name-pattern | 日志存檔的文件名格式(默認(rèn)值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz) |
logging.logback.rollingpolicy.clean-history-on-start | 應(yīng)用啟動(dòng)時(shí)是否清除以前存檔(默認(rèn)值:false) |
logging.logback.rollingpolicy.max-file-size | 存檔前,每個(gè)日志文件的最大大?。J(rèn)值:10MB) |
logging.logback.rollingpolicy.total-size-cap | 日志文件被刪除之前,可以容納的最大大?。J(rèn)值:0B)。設(shè)置1GB則磁盤(pán)存儲(chǔ)超過(guò) 1GB 日志后就會(huì)刪除舊日志文件 |
logging.logback.rollingpolicy.max-history | 日志文件保存的最大天數(shù)(默認(rèn)值:7). |
例:
logging.file.name=D:\logs\my.log
# LOG_FILE:代表我們配置的日志文件名,如my.log
# yyyy-MM-dd:年月日
# %i:代表當(dāng)天第幾個(gè)文件
logging.logback.rollingpolicy.file-name-pattern=${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
# 只要my.log日志文件大于10MB就會(huì)觸發(fā)日志歸檔,將當(dāng)前日志文件壓縮為my.log.2019-01-01.1.gz
logging.logback.rollingpolicy.max-file-size=10MB九、自定義配置
通常我們配置 application.properties 就夠了。當(dāng)然也可以自定義。比如:
日志系統(tǒng) | 自定義 |
Logback | logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
如果可能,我們建議您在日志配置中使用-spring 變量(例如,logback-spring.xml 而不是 logback.xml)。如果您使用標(biāo)準(zhǔn)配置文件,spring 無(wú)法完全控制日志初始化。
最佳實(shí)戰(zhàn):自己要寫(xiě)配置,配置文件名加上 xx-spring.xml
十、切換日志組合
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>哪怕你切換log4j2,你也不用改任何代碼和配置,這就是日志門(mén)面的好處。
到此這篇關(guān)于SpringBoot整合日志功能(slf4j+logback)詳解的文章就介紹到這了,更多相關(guān)SpringBoot整合slf4j+logback內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于newFixedThreadPool實(shí)現(xiàn)多線程案例
這篇文章主要介紹了基于newFixedThreadPool實(shí)現(xiàn)多線程案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
使用Java實(shí)現(xiàn)獲取文件MD5值工具類(lèi)
我們?cè)诠ぷ髦型ǔJ褂肕D5對(duì)文件進(jìn)行校驗(yàn)完整性,比較,提高安全性等,這篇文章主要為大家詳細(xì)介紹了Java如何編寫(xiě)一個(gè)實(shí)現(xiàn)獲取文件MD5值的工具,需要的可以參考下2023-12-12
谷歌二維碼引擎com.google.zxing二維碼生成與解析
這篇文章主要給大家介紹了關(guān)于谷歌二維碼引擎com.google.zxing二維碼生成與解析的相關(guān)資料,zxing是google開(kāi)源的二維碼生成和解析工具,需要的朋友可以參考下2023-07-07
淺析Java中靜態(tài)代理和動(dòng)態(tài)代理的應(yīng)用與區(qū)別
代理模式在我們生活中很常見(jiàn),而Java中常用的兩個(gè)的代理模式就是動(dòng)態(tài)代理與靜態(tài)代理,這篇文章主要為大家介紹了二者的應(yīng)用與區(qū)別,需要的可以參考下2023-08-08
Spring Boot 安全 API 構(gòu)建之加密解密功能的實(shí)踐記錄
本文詳述了如何在SpringBoot3.3環(huán)境中實(shí)施API加密的最佳實(shí)踐,包括選擇合適的加密算法,密鑰管理,數(shù)據(jù)加密,防止加密漏洞,安全日志記錄,測(cè)試和監(jiān)控等方面,同時(shí),文章也對(duì)RSA非對(duì)稱加密和AES對(duì)稱加密的實(shí)現(xiàn)步驟進(jìn)行了詳細(xì)的解析2024-10-10
Java的Lambda表達(dá)式和Stream流的作用以及示例
這篇文章主要介紹了Java的Lambda表達(dá)式和Stream流簡(jiǎn)單示例,Lambda允許把函數(shù)作為一個(gè)方法的參數(shù),使用Lambda表達(dá)式可以寫(xiě)出更簡(jiǎn)潔、更靈活的代碼,而其作為一種更緊湊的代碼風(fēng)格,使Java的語(yǔ)言表達(dá)能力得到了提升,需要的朋友可以參考下2023-05-05
Java讀取json數(shù)據(jù)并存入數(shù)據(jù)庫(kù)的操作代碼
很多朋友問(wèn)大佬們JAVA怎么把json存入數(shù)據(jù)庫(kù)啊,這一問(wèn)題就把我難倒了,糾結(jié)如何操作呢,下面小編把我的經(jīng)驗(yàn)分享給大家,感興趣的朋友一起看看吧2021-08-08

