SLF4J user manual

一个简单的面向java的日志门面,或者定义为一个面向各种日志框架的抽象。
例如java.util.logging、logback、log4j。slf4j允许最终用户只需要在开发阶段添加希望的日志框架,只需要一个简单的依赖slf4j-api-1.7.21.jar就能完成实现。

从1.6.0开始 如果在绑定的calsspath上没有发现slf4j,那么slf4j将不会起作用。

从1.7.0开始 接口的打印方法提供一种变种的方式代替数组接收可变参数,
这个变化需要jdk5或者更高级版本。在后台java编译器把可变参数转变为数组,
这样日志接口编译后1.7和1.6就没什么区别了。所以slf4j1.7版本对于jdk1.6肯定没问题了。

从1.7.5开始 已经进行多次重大的提升,很大程度的改善鼓励用户去迁移到更加高级版本中

从1.7.9开始 通过设置slf4j日志名称不匹配系统参数默认打开为true,slf4j可以自动指出不正确的命名日志

Hello World

按照编程习惯来说,这是一个使用slf4j简单方法输出“Hello World”的例子。
首先得到得到一个logger 通过HelloWorld。这个logger来输出日志“Hello World”

1
2
3
4
5
6
7
8
9
10
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}

为了运行这个例子首先下载slf4j-api.jar把这个放到项目的classpath中,编译后运行main方法,
在控制台得到如下输出

1
2
3
4
log4j:WARN No appenders could be found for logger (com.cninsure.service.IPolicyInfoServiceTest)
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

这个警告是因为在classpath上没有绑定日志框架。加上slf4j-simple.jar 然后运行控制台输出

1
2
[main] INFO HelloWorld - Hello World

典型使用模式

下面这个是经典使用方式,注意{}第五行的占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Wombat {
final Logger logger = LoggerFactory.getLogger(Wombat.class);
Integer t;
Integer oldT;
public void setTemperature(Integer temperature) {
oldT = t;
t = temperature;
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
if(temperature.intValue() > 50) {
logger.info("Temperature has risen above 50 degrees.");
}
}
}

在开发时绑定一个日志框架

向以前已经提到一样,slf4j支持多种日志框架。slf4j提供了多种jar文件例如“SLF4J 日志框架”
每一个绑定都和支持的日志框架一致。


slf4j-log4j12-1.7.21.jar

绑定的log4j版本是1.2,这个版本非常流行,当然你也需要log4j的jar包。


slf4j-jdk14-1.7.21.jar

绑定了 java.util.logging,并且要求JDK 1.4


slf4j-nop-1.7.21.jar

绑定了NOP日志框架,但是他会丢弃所有的日志


slf4j-simple-1.7.21.jar

对于简单的系统这个日志框架比较适用


slf4j-jcl-1.7.21.jar

这个是apache的日志框架。


logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)

基础实现 当然也有slf4j绑定完全不相关的SLF4J项目。e.g.logback实现了slf4j
接口。所以slf4j和loback结合使用占用更少的内存打到更快的速度

切换日志框架时只需要替换slf4j绑定即可

SLF4J并不依赖任何特殊的类加载器,事实上每个slf4j绑定都是在编译期间加入的。
不要同时使用两种,日志框架

SLF4J的接口和他多种适配日志框架十分简单,不需要类加载器。所以SLF4J并没有类加载问题,
也没有和JCL一样的内存问题。slf4j的扩展性不错

依赖库

作为对外贡献插件或者依赖库的开发人员来说slf4j能够避免组件的使用者引入依赖组件或者库的日志框架。这样引用者可以在自己的系统引入自己想用的日志框架了。

在1.6.0版本,如果系统没有发现绑定日志框架,slf4j-api会默认不采取行动去实现已经写好的日志请求,而不是抛出classnotfounderro.应为org.slf4j.impl.StaticLoggerBinder这个类不存在。
在以后的版本中将会指出一个简单警告关于缺少绑定,并且放弃所有的日志输出。举了一个树袋熊的例子含义还是,我只是用slf4j-api,我自己在代码内部使用了slf4j日志输出,
按理说所有引用第三方组件库的开发者必须在自己的系统中使用slf4j的相关的日志框架实现,
否则所有的日志都会看不到。

总结 作为组件的提供方,我自己的功能里面的必须添加slf4j-api,进行组件的开发调试恶意添加自己的slf4j日志绑定框架。但是我对外打包时必须去掉我自己在调试时引用的相关日志框架,这样在调用方引入自己的日志框架时才不会报错。组件的引用方。必须引入一种和slf4j绑定的日志矿建,否则第三方的日志输出看不到。

二进制兼容性

组件提供方使用的slf4j-api.jar的任何版本都可以。只需要引用方引入相应的slf4j绑定日志框架即可,因为引用方会覆盖提供方的版本。提供方使用1.7.2。引用方式使用1.5.5。提供方的日志依然能用。

Mapped Diagnostic Context (MDC) support

MDC本质上是一个有特性上下文的map,日志框架提供一个key-value的组合能够记录在日志框架中。MDC对于过滤信息非常有用,记录关键行为。

slf4j支持MDC。如果绑定的日志框架支持MDC(log4j、logback),
slf4j会发不成日志框架的样式(java.util.logging)。如果日志框架不支持,slf4j还是会存储信息,但是样式需要开发人员自己取编码了。

总结 这个MDC简单来说就是日志输出头的定制。这个对于后期做日至分析相当重要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//编码
package chapters.mdc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.core.ConsoleAppender;
public class SimpleMDC {
static public void main(String[] args) throws Exception {
// You can put values in the MDC at any time. Before anything else
// we put the first name
MDC.put("first", "Dorothy");
[ SNIP ]
Logger logger = LoggerFactory.getLogger(SimpleMDC.class);
// We now put the last name
MDC.put("last", "Parker");
// The most beautiful two words in the English language according
// to Dorothy Parker:
logger.info("Check enclosed.");
logger.debug("The most beautiful two words in English.");
MDC.put("first", "Richard");
MDC.put("last", "Nixon");
logger.info("I am not a crook.");
logger.info("Attributed to the former US president. 17 Nov 1973.");
}
[ SNIP ]
}

1
2
3
4
5
6
7
//日志框架配置文件
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout>
<Pattern>%X{first} %X{last} - %m%n</Pattern>
</layout>
</appender>
1
2
3
4
5
6
//日志输出格式
Dorothy Parker - Check enclosed.
Dorothy Parker - The most beautiful two words in English.
Richard Nixon - I am not a crook.
Richard Nixon - Attributed to the former US president. 17 Nov 1973.

执行概要

| 优势                          | 描述               |
| ---------------------------- |:------------------:|
| 在开发时选择自己的日志框架      |直接加入slf4j相应的绑定日志框架即可|
| 操作快速失败    | 由于jvm加载类,引入的日志框架自动早期检测。如果slf4j没有检测到任何绑定,slf4j会马上给出警告。并且不会输出任何日志 |
| 绑定了现在流行的日志框架 | slf4j支持现在流行的框架例如log4j、java.util.logging、logback(在底层上支持)、simple logging、NOP、 |
|兼容老版本||
|迁移源代码|slf4j-migrator 可以有效的帮助你迁移log4j、jcl源码到slf4j|
|支持参数式日志信息|logger.debug("Value {} was inserted between {} and {}.", newVal, below, above);<br>这种形式代替<br>logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));