spring?boot?Slf4j日志框架的體系結(jié)構(gòu)詳解
前言
剛剛接觸到j(luò)ava log日志的同學(xué)可能會被各種日志框架嚇到,包括各種日志框架之間的jar總是發(fā)生沖突,另很多小伙伴頭疼不已。那我們本篇的內(nèi)容就是將各種java 日志框架發(fā)展過程,以及他們之間的關(guān)系,以及如何選型來介紹給大家。
一、五花八門的日志工具包
1.1. 日志框架
- JDK java.util.logging 包:java.util.logging 是 jdk1.4 發(fā)布的 java 日志包, 可以說是應(yīng)用比較久遠(yuǎn)的日志工具包
- log4j: apache 的一個開源項目,提供了強有力的 java 日志支持,甚至他也提供了其他語言包括 C、C++、.Net、PL/SQL 的接口,從而實現(xiàn)多語言并存的分布式環(huán)境日志打印。目前已經(jīng)停止更新,所以不推薦使用。
- Logback:由log4j創(chuàng)始人設(shè)計的另一個開源日志組件,作為Spring Boot默認(rèn)的日志框架,應(yīng)用比較廣泛。
- log4j2 :Apache Log4j2是對Log4j的升級,它比其前身Log4j1.x提供了重大改進(jìn),并提供了Logback中可用的許多改進(jìn),同時修復(fù)了Logback架構(gòu)中的一些問題。它基于LMAX公司開發(fā)Disruptor(一個開源的無鎖并發(fā)框架),改善了Log4j和Logback在架構(gòu)設(shè)計方面的缺陷,具有超高的吞吐量和低延遲,性能比Log4j1.x和Logback更好。
1.2.日志門面
- commons-logging: Apache commons類庫中的一員,他作為一個日志門面,能夠自動選擇使用 log4j 還是 JDK logging,但是他不依賴Log4j,JDK Logging的API。如果項目的classpath中包含了log4j的類庫,就會使用log4j,否則就使用JDK Logging。
- SLF4J: 可以說是目前應(yīng)用最為廣泛的日志門面了,它提供了一個日志抽象層,允許你在后臺使用任意一個日志類庫。如:log4j、log4j2、logback
1.3日志門面存在的意義
為什么不直接使用日志框架,而是搞出一個日志門面?
日志門面(SLF4J)主要是為了給Java日志訪問提供一套標(biāo)準(zhǔn)、規(guī)范的API框架,其主要意義在于提供接口,具體的實現(xiàn)可以交由其他日志框架來實現(xiàn),例如log4j和logback等。 對于一般的Java項目而言,日志框架會選擇slf4j-api作為門面,配上具體的實現(xiàn)框架(log4j、log4j2、logback等),中間使用橋接器完成橋接。
前面介紹的幾種日志框架,每一種日志框架都有自己單獨的API,要使用對應(yīng)的框架就要使用其對應(yīng)的API,這就大大的增加應(yīng)用程序代碼對于日志框架的耦合性要求。有了SLF4J這個門面之后,程序員永遠(yuǎn)都是面向SLF4J編程,可以實現(xiàn)簡單快速地替換底層的日志框架而不會導(dǎo)致業(yè)務(wù)代碼需要做相應(yīng)的修改。
在使用 SLF4J 進(jìn)行日志記錄時,通常都需要在每個需要記錄日志的類中定義 Logger 變量,如下所示:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RestController public class LogTestController { private static final Logger logger = LoggerFactory.getLogger(LogTestController.class); @GetMapping("/test") public void test(){ logger.trace("Trace 日志..."); logger.debug("Debug 日志..."); logger.info("Info 日志..."); logger.warn("Warn 日志..."); logger.error("Error 日志..."); } }
這顯然屬于重復(fù)性勞動,降低了開發(fā)效率,如果你在項目中引入了 Lombok,那么可以使用它提供的 @Slf4j 注解來自動生成上面那個變量,默認(rèn)的變量名是 log,如果我們想采用慣用的 LOGGER作為 變量名,那么可以在工程的根目錄中增加 lombok.config 文件,并在文件中增加lombok.log.fieldName=LOGGER
的配置項即可。
二、日志框架選型
- Spring Boot 默認(rèn)的日志記錄框架使用的是 Logback
- 其中 Log4j 可以認(rèn)為是一個過時的函數(shù)庫,已經(jīng)停止更新,不推薦使用,相比之下,性能和功能也是最差的。
- logback 雖然是 Spring Boot 默認(rèn)的,但性能上還是不及 Log4j2,因此,在現(xiàn)階段,日志記錄首選 Log4j2(log4j系列經(jīng)歷了安全風(fēng)波,請選用漏洞修復(fù)后的新版本)。
SLF4J + Log4j2 是我們推薦的日志記錄選型。
性能測試結(jié)果
三、日志級別
細(xì)說各日志框架整合配置前,我們先來大致了解下,最常見的日志的幾個級別:ERROR, WARN, INFO, DEBUG和TRACE。像其他的,比如ALL、OFF和FATAL之類的開發(fā)過程中應(yīng)該基本上是不會涉及的。所以以下從低到高一次介紹下常見的日志級別。
- TRACE:追蹤。一般上對核心系統(tǒng)進(jìn)行性能調(diào)試或者跟蹤問題時有用,此級別很低,一般上是不開啟的,開啟后日志會很快就打滿磁盤的。
- DEBUG:調(diào)試。這個大家應(yīng)該不陌生了。開發(fā)過程中主要是打印記錄一些運行信息之類的。
- INFO:信息。這個是最常見的了,大部分默認(rèn)就是這個級別的日志。一般上記錄了一些交互信息,一些請求參數(shù)等等??煞奖愣ㄎ粏栴},或者還原現(xiàn)場環(huán)境的時候使用。此日志相對來說是比較重要的。
- WARN:警告。這個一般上是記錄潛在的可能會引發(fā)錯誤的信息。比如啟動時,某某配置文件不存在或者某個參數(shù)未設(shè)置之類的。
- ERROR:錯誤。這個也是比較常見的,一般上是在捕獲異常時輸出,雖然發(fā)生了錯誤,但不影響系統(tǒng)的正常運行。但可能會導(dǎo)致系統(tǒng)出錯或是宕機等。
日志級別從小到大為trace<debug<info<warn<error<fatal,由于通常日志框架默認(rèn)日志級別設(shè)置為INFO,因此1.3.小節(jié)中樣例trace和debug級別的日志都看不到。
2020-08-17 13:59:16.566 INFO c.z.b.l.controller.LogTestController : Info 日志... 2020-08-17 13:59:16.566 WARN c.z.b.l.controller.LogTestController : Warn 日志... rn 日志... 2020-08-17 13:59:16.566 ERROR c.z.b.l.controller.LogTestController : Error 日志...
四、常見術(shù)語概念解析
- appender:主要控制日志輸出到哪里,比如:文件、數(shù)據(jù)庫、控制臺打印等
- logger: 用來設(shè)置某一個包或者具體某一個類的日志打印級別、以及指定appender
- root:也是一個logger,是一個特殊的父logger。所有的子logger最終都會將輸出流交給root,除非在子logger中配置了additivity=“false”。
- rollingPolicy:所有日志都放在一個文件是不好的,所以可以指定滾動策略,按照一定周期或文件大小切割存放日志文件。
- RolloverStrategy:日志清理策略。通常是指日志保留的時間。
- 異步日志:單獨開一個線程做日志的寫操作,達(dá)到不阻塞主線程的目的。
- 同步日志,主線程要等到日志寫磁盤完成之后,才能繼續(xù)向下執(zhí)行
- 異步日志,主線程寫日志只是將日志消息放入一個隊列,之后就繼續(xù)向下執(zhí)行,這個過程是在內(nèi)存層面完成的。之后由專門的線程從隊列中獲取日志數(shù)據(jù)寫入磁盤,所以不阻塞主線程。主線程(核心業(yè)務(wù)代碼)執(zhí)行效率很高。
總結(jié)
到此這篇關(guān)于spring boot Slf4j日志框架的體系結(jié)構(gòu)詳解的文章就介紹到這了,更多相關(guān)springboot Slf4j日志框架內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java生成隨機數(shù)之Random與ThreadLocalRandom性能比較詳解
大家項目中如果有生成隨機數(shù)的需求,我想大多都會選擇使用Random來實現(xiàn),它內(nèi)部使用了CAS來實現(xiàn)。?實際上,JDK1.7之后,提供了另外一個生成隨機數(shù)的類ThreadLocalRandom,那么他們二者之間的性能是怎么樣的呢?本文就來詳細(xì)說說2022-12-12java中如何實現(xiàn) zip rar 7z 壓縮包解壓
這篇文章主要介紹了java中如何實現(xiàn) zip rar 7z 壓縮包解壓問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07springcloud如何使用dubbo開發(fā)rpc服務(wù)及調(diào)用
這篇文章主要介紹了springcloud如何使用dubbo開發(fā)rpc服務(wù)及調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01Apache Shrio安全框架實現(xiàn)原理及實例詳解
這篇文章主要介紹了Apache Shrio安全框架實現(xiàn)原理及實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04JAVA Spring中讓人頭痛的JAVA大事務(wù)問題要如何解決你知道嗎
這篇文章主要介紹了Java Spring事務(wù)使用及驗證過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2021-09-09JDK14新特性之switch表達(dá)式的實現(xiàn)
這篇文章主要介紹了JDK14新特性之switch表達(dá)式的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05如何用Java?幾分鐘處理完?30?億個數(shù)據(jù)(項目難題)
現(xiàn)有一個 10G 文件的數(shù)據(jù),里面包含了 18-70 之間的整數(shù),分別表示 18-70 歲的人群數(shù)量統(tǒng)計,今天小編通過本文給大家講解如何用Java?幾分鐘處理完?30?億個數(shù)據(jù),這個問題一直以來是項目難題,今天通過本文給大家詳細(xì)介紹下,感興趣的朋友一起看看吧2022-07-07