520
技術社區[雲棲]
SLF4J 使用手冊
Java的簡單日誌門麵( Simple Logging Facade for Java SLF4J)作為一個簡單的門麵或抽象,用來服務於各種各樣的日誌框架,比如java.util.logging、logback和log4j。SLF4J允許最終用戶在部署時集成自己想要的日誌框架。
需要注意的是,你的應用啟用SLF4J意味著需要一個額外的依賴:slf4j-api-1.7.19.jar。
從1.6.0開始:如果在class path沒有找到綁定,SLF4J將默認一個無操作的實現。
從1.7.0開始:Logger接口中的打印方法現在提供variants取代了Object[]用來接收可變長參數。這個改變意味著SLF4J需要JDK 1.5或更高的版本。Java編譯器在底層把方法中的可變參數部分轉換成Object[]。因此,編譯器生成的Logger接口在1.7.x版本中和它對應的的1.6.x版本中是沒有區別的。因此SLF4J得1.7.x版本和1.6.x版本是 完全兼容的。
從1.7.5開始:日誌的檢索時間有了一個顯著的改善,鑒於這個改善,非常鼓勵用戶遷移到SLF4J 1.7.5或更高的版本。
從1.7.9開始: 通過設置 slf4j.detectLoggerNameMismatch
係統屬性為true,SLF4J能自動的 spot incorrectly named loggers.
Hello World
1 |
import org.slf4j.Logger;
|
2 |
import org.slf4j.LoggerFactory;
|
3 |
4 |
public class HelloWorld {
|
5 |
public static void main(String[] args) {
|
6 |
Logger logger = LoggerFactory.getLogger(HelloWorld. class );
|
7 |
logger.info( "Hello World" );
|
8 |
}
|
9 |
} |
運行這個示例,首先你需要下載slf4j發行版 download the slf4j distribution,然後解壓。做完這些之後,把 slf4j-api-1.7.19.jar添加到你的class path。
編譯運行HelloWorld,控製台將有一下輸出:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See https://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
這個警告會被打印是因為在class path下沒有找到綁定的slf4j。
一旦你添加一個綁定在你的class path下,這個警告將會消失。假設你添加了 slf4j-simple-1.7.19.jar,你的class path包含:
- slf4j-api-1.7.19.jar
- slf4j-simple-1.7.19.jar
編譯並運行HelloWorld程序,現在在控製台會有下列輸出:
0 [main] INFO HelloWorld - Hello World
典型使用模式
下麵的示例代碼表明了SLF4J的典型使用模式。注意15行”{}“的使用,查看 “What is the fastest way of logging?”獲取更多細節。
1: import org.slf4j.Logger; 2: import org.slf4j.LoggerFactory; 3: 4: public class Wombat { 5: 6: final Logger logger = LoggerFactory.getLogger(Wombat.class); 7: Integer t; 8: Integer oldT; 9: 10: public void setTemperature(Integer temperature) { 11: 12: oldT = t; 13: t = temperature; 14: 15: logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT); 16: 17: if(temperature.intValue() > 50) { 18: logger.info("Temperature has risen above 50 degrees."); 19: } 20: } 21: }
在部署時綁定一個日誌框架
像在之前提到過的,SLF4J支持各種各樣的日誌框架。SLF4J的發行版附帶的幾個jar被稱為” SLF4J bindings“ ,每個綁定都對應一個支持的框架。
slf4j-log4j12-1.7.19.jar
綁定 log4j version 1.2,一個廣泛使用的日誌框架,你也需要在class path放置 log4j.jar。
slf4j-jdk14-1.7.19.jar
綁定 java.util.logging,也被稱為JDK 1.4 日誌。
slf4j-nop-1.7.19.jar
綁定 NOP,默默地打出所有的日誌。
slf4j-simple-1.7.19.jar
綁定 Simple實現,輸出所有的System.err事件,隻有INFO和更高級別的信息會被打印。這個綁定或許 在小應用程序的上下文中非常有用。
logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)
本地實現:也有SLF4J的綁定在SLF4J項目之外,比如 logback 在本地實現了SLF4J。Logback的 ch.qos.logback.classic.Logger
類直接實現了SLF4J的 org.slf4j.Logger
接口。因此,和logback一起使用SLF4J涉及到嚴格零內存和計算開銷。
切換日誌框架,隻需要替換class path中的slf4j綁定。比如說,從 java.util.logging切換到 log4j,僅僅把 slf4j-jdk14-1.7.19.jar替換成 slf4j-log4j12-1.7.19.jar。
SLF4J不依賴於特定的類加載機製。事實上,每個SLF4J綁定在編譯時硬連接來使用一個指定的日誌框架。比如說, slf4j-log4j12-1.7.19.jar在編譯時綁定使用log4j。在你的代碼中,除 slf4j-api-1.7.19.jar之外,隻能有一個你選擇的綁定 到正確的class path 路徑上。不要在class path 放置多個綁定。下麵是一個圖表來說明一般的想法。
SLF4J接口和他們的各種各樣的適配器非常簡單。大多數熟悉Java語言的開發者應該能在一小時之內讀懂代碼。不需要類加載的知識。因此,SLF4J沒有遭受類加載問題或者 Jakarta Commons Logging (JCL)觀察到的內存泄露問題。
鑒於SLF4J接口的簡單性和它的部署模型,新的日誌框架開發者應該覺得很容易編寫SLF4J綁定。
庫
為了避免給他們的終端用戶強加一個日誌框架 ,一些組件和庫的作者可能會針對SLF4J接口進行編程。因此,終端用戶在部署時可以通過在classpath插入對應的slf4j綁定來選擇他們期望的日誌框架。並且,可以把在classpath存在的綁定替 換到另外一個,然後重啟應用,從而達到切換日誌框架的目的,這個方法被證明是非常簡單和健壯的。
SLF4J的1.6.0版本,如果在class path 沒有發現綁定,slf4j-api將默認一個無操作的實現來忽略所有的日誌請求。因此,SLF4J從1.6.0版開始發出一個缺少綁定的警告,然後丟棄所有的打印日誌請求,而不是拋出 NoClassDefFoundError
異 常因為缺少 org.slf4j.impl.StaticLoggerBinder
類 。比如說: Wombat 一些基礎框架依賴於SLF4J來打印日誌。為了避免強加一個日誌框架給終端用戶,Wombat 包含 slf4j-api.jar但是沒有綁定。在class path 沒有SLF4J綁定的情 況下,Wombat的發行版依然能開箱即用,不需要終端用戶下載從SLF4J網站下載一個綁定。僅僅當終端用戶開啟日誌的時候,將需要安裝他選擇的日誌框架對應的SLF4J綁定。
基本準則:內置的組件比如庫和框架不應該聲明任何SLF4J的依賴,但是依賴於SLF4J-api。當一個庫在一個指定的綁定聲明一個傳遞依賴,這個強加於終端用戶的綁定否定了SLF4J的目的。注意,在綁定上聲明一個非傳遞性的依賴,比如說 對測試,不影響終端用戶。
內嵌組件中SLF4J的使用也在FAQ中進行討論。有關係的章節: logging configuration dependency reduction testing
聲明項目的日誌依賴
鑒於Maven的傳遞依賴規則,對於”regular“項目(不是庫和框架),日誌依賴聲明 可以通過一個單獨的依賴聲明來實現。
LOGBACK-CLASSIC: 如果你希望使用 logback-classic 作為底層的日誌框架,你需要做的所有事情就是聲明” ch.qos.logback:logback-classic“依賴到你的pom.xml文件中。除了 logback-classic-1.0.13.jar之外,它將拉取 slf4j-api-1.7.19.jar和 logback-core-1.0.13.jar 到你的項目中。注意,顯式的聲明 logback-core-1.0.13或 slf4j-api-1.7.19.jar 沒有錯,並且可能需要強加一個正確的版本。
1 |
<dependency> |
2 |
<groupId>ch.qos.logback</groupId>
|
3 |
<artifactId>logback-classic</artifactId>
|
4 |
<version> 1.0 . 13 </version>
|
5 |
</dependency> |
LOG4J:如果你希望使用log4j作為底層的日誌框架,你需要做的所有事情就是聲明” org.slf4j:slf4j-log4j12“依賴到你的pom.xml文件中。除了 slf4j-log4j12-1.7.19.jar之外,它將拉取 slf4j-api-1.7.19.jar和 log4j-1.2.17.jar到你的項目 中。注意,顯示地聲明一個依賴 log4j-1.2.17.jar或 slf4j-api-1.7.19.jar 沒有錯。並且可能需要強加一個正確的版本
1 |
<dependency> |
2 |
<groupId>org.slf4j</groupId>
|
3 |
<artifactId>slf4j-log4j12</artifactId>
|
4 |
<version> 1.7 . 19 </version>
|
5 |
</dependency> |
JAVA.UTIL.LOGGING:如果你希望使用 java.util.logging 作為底層的日誌框架,你需要做的所有事情就是聲明” org.slf4j:slf4j-jdk14“依賴到你的pom.xml文件中。除了 slf4j-jdk14-1.7.19.jar之外,它將拉取 slf4j-api-1.7.19.jar到你 的項目中。注意,顯示地聲明一個依賴 slf4j-api-1.7.19.jar 沒有錯。並且可能需要強加一個正確的版本。
1 |
<dependency> |
2 |
<groupId>org.slf4j</groupId>
|
3 |
<artifactId>slf4j-jdk14</artifactId>
|
4 |
<version> 1.7 . 19 </version>
|
5 |
</dependency> |
二進製兼容
一個SLF4J綁定指定一個具體的依賴用來在底層日誌框架綁定slf4j,比如說 slf4j-jdk14.jar或 slf4j-log4j12.jar。
不同版本的 slf4j-api.jar和SLF4J綁定混合在一起可能會引起問題。比如說,如果你使用 slf4j-api-1.7.19.jar,然後你應該使用 slf4j-simple-1.7.19.jar,使用 slf4j-simple-1.5.5.jar將不會正常工作。
然而,從客戶端的觀點來看,所有版本的 slf4j-api都是兼容的。使用 slf4j-api-N.jar編譯的客戶端代將和 slf4j-api-M.jar一起完美運行,N和M都是任意的。你僅僅需要確保你綁定的版本和 slf4j-api.jar 匹配。你不需要擔心項目中給定的依 賴的slf4j-api.jar的版本。你可以使用任何版本的 slf4j-api.jar,隻要 slf4j-api.jar的版本和它的綁定匹配,就不會有問題。
在初始化的時間,如果SLF4J懷疑可能有不匹配問題。將會發出關於不匹配的警告信息。
通過SLF4J統一日誌
通常,一個給定的項目依賴於各種各樣的組件,這些組件依賴的日誌API不是SLF4J。一個項目依賴於一個JCL、java.util.logging、log4j和SLF4J是很常見的。然後通過一個單獨的方式來統一日誌變得讓人滿意。SLF4J通過提供對JCL、
java.util.logging、和slf4j的橋接模塊來滿足這個普通的用例。更詳細的內容,請參考 Bridging legacy APIs.
MDC支持
“Mapped Diagnostic Context”本質上是日誌框架包含的一個map,應用程序代碼提供了key-value對,這個鍵值對能被日誌框架插入到日誌信息中去。MDC數據在過濾信息或觸發某些操作時是非常有用的。
SLF4J支持MDC,如果一個底層的日誌框架提供了MDC功能,SLF4J將委托給底層日誌框架的MDC。注意,現在僅僅隻有log4j和logback提供了MDC功能。如果底層日誌框架不支持MDC,比如說java.util.loggin,SLF4J將存儲MDC數 據,但是裏麵的數據需要用戶通過代碼來獲取。
因此,作為一個SLF4J使用者,能利用當 log4j和logback存在時的 MDC信息,但是不能強迫用戶依賴這些日誌框架。
關於MDC的更多信息參見 chapter on MDC
行動綱要
Advantage | Description |
在部署時候選擇日誌框架 | 通過在class path插入合適的jar,期望的日誌框架能在部署時集成。 |
快速失敗操作 | 由於虛擬機加載類的方式,很早就自動驗證框架綁定。如果SLF4J沒有在class path 發現一個綁定,它將會發出一個警告信息,並且默認一個無操作的實現。 |
綁定流行的日誌框架 | SLF4J支持流行的日誌框架,log4J、java.util.logging、Simple logging和NOP。 logback天生支持SLF4J。 |
橋接遺留的logging APIs | 通過SLF4J實現JCL,如 jcl-over-slf4j.jar,將允許項目遷移到SLF4J,沒有破壞使用JCL的軟件的兼容性。同樣的, log4j-over-slf4j.jar 和 jul-to-slf4j模塊重定向log4j到SLF4J。查看 Bridging legacy APIs 獲取更多信息 |
移動你的源碼 | slf4j-migrator工具能幫助你遷移你的代碼來使用SLF4J。 |
支持參數化的日誌信息 | 所有的SLF4J綁定支持參數化的日誌信息。並且可以顯著提高性能。 improved performance |
最後更新:2017-05-19 17:02:24