面試題:應用中不少jar包,好比spring、mybatis、redis等等,各自用的日誌系統各異,怎麼用slf4j統一輸出?(上)

1、問題概述

如題所說,後端應用(非spring boot項目)一般用到了不少jar包,好比spring系列、mybatis、hibernate、各種鏈接數據庫的客戶端的jar包。可能這個jar包用的是logback、那個用的是log4j、那個又是log4j2,java

這時候,怎麼才能保證各jar包的日誌都能輸出,且能以統一的格式輸出呢?git

 

爲何要強調非spring boot項目,可參考第四節。github

2、幾種日誌框架的簡單介紹

來源:https://juejin.im/post/5a7c5d575188254e76179c0fspring

Java中的日誌框架分以下幾種:數據庫

1.Log4j   

 Apache Log4j是一個基於Java的日誌記錄工具。它是由Ceki Gülcü獨創的,如今則是Apache軟件基金會的一個項目。apache

2.Log4j 2

Apache Log4j 2是apache開發的一款Log4j的升級產品。編程

3.Commons Logging

Apache基金會所屬的項目,是一套Java日誌接口,以前叫Jakarta Commons Logging,後改名爲Commons Logging。後端

4.Slf4j

Slf4j 相似於Commons Logging,是一套簡易Java日誌門面,自己並沒有日誌的實現。(Simple Logging Facade for Java,縮寫Slf4j)。api

5.Logback

一套日誌組件的實現(slf4j陣營)。mybatis

6.Jul (Java Util Logging)

自Java1.4以來的官方日誌實現。

 

上面這幾個框架,又分爲了兩類:一類是接口,包括了slf4j、commons logging;剩下的幾個是具體實現,包括了jul、logback、log4j、log4j2。

如今,講究針對接口編程,而不是針對具體實現,方便移植。而如今最通用的就是slf4j。就我待過的幾家公司來講,全都都用的是slf4j做爲日誌門面,具體的實現通常直接採用默認的logback。

下面就具體講講,怎麼將其餘框架五花八門的日誌一統爲slf4j。

 

3、統一的思路

咱們先分析下。

假設有個jar採用了JUL,即java自帶的日誌系統。咱們要怎麼才能將其適配到slf4j去呢?

在JUL的logger的方法被調用時,由於Logger所在的包位於java.util,默認就被加載了,不太方便以假亂真。

想要覆蓋其實現,我能想到的是,經過aop切面,直接將參數傳給slf4j的api,不調用原來的日誌實現。

 

再來,假設有個jar採用了log4j,即寫日誌用的是org.apache.log4j.Logger,該類是來源於log4j的相關jar包,那麼,

我能夠排除掉log4j相關的jar包,代碼裏報錯了,對吧?那我再建一個相同package名、相同類名的class。在這個假的

class裏,我去調用slf4j的api。

 

那麼,這些功能須要我本身去寫嗎?不須要!slf4j已經給咱們提供了從各種日誌框架九九歸一到slf4j的轉換包。

源日誌框架 目標日誌框架 所需轉換用jar包 maven(這裏缺了version字段,請參考下一節)  備註
jul   slf4j
jul-to-slf4j
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
 須要排除掉原有依賴。
Commons Logging slf4j
jcl-over-slf4j
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>

須要排除掉原有依賴。

log4j slf4j
log4j-over-slf4j
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
須要排除掉原有依賴。
log4j2 slf4j  
log4j-to-slf4j
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.8.2</version>
</dependency>

須要排除掉原有依賴。

注意這裏使用的爲

log4j-to-slf4j

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

這裏給一張slf4j官方手冊裏的,也是漏了log4j2的。

 

4、如何選擇以上轉換jar包的版本

在spring boot中,其實根本不須要以上的麻煩工做,只須要引用如下組件:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
咱們看看這個組件裏,包含了什麼:

 

能夠看到,log4j、jul、jcl(即commons-logging)的轉換包都有了。

那麼,在非spring boot項目中,咱們只要去mvnrepository.com查詢:spring-boot-starter-logging.
而後,選擇對應的版本,就能夠在下圖看到該組件依賴的包:

 

怎麼樣,應該是個比較簡單的辦法吧?

 

5、未完成的統一之路

這一篇裏面,咱們還只講瞭如何將各日誌框架統一到slf4j來。

可是slf4j只是個門面,具體的實現呢(好比log4j等)又被咱們排除掉了。

那麼slf4j沒有實現,也是不能完成輸出日誌的任務的。

因此咱們還須要一個實現。這份留到下篇仔細講。

 

6、github代碼(已實現上述的統一問題,默認實現採用了logback)

代碼路徑:

https://github.com/cctvckl/logtest

 

這裏演示下效果:

 

下面是統一後的:

 

其中jul爲何日誌未統一,等有時間了我再看看。這兩天時間有點緊,要開發需求。。。

相關文章
相關標籤/搜索