SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。
看SLF4J的英文的F-facade(外表),就知道SLF4J只是一个只有“外表”的东西,也就是它没有提供具体的实现类,只提供一个定义的接口。所以他需要与log4j这种已实现的日志包一起使用。在程序的调用过程中,程序只会直接调用SLF4J的类实例,而不会出现log4j的实例。
总结上述:slf4j是一个日志框架,log4j是一个日志系统。
当然啦,也有人说为什么不直接用log4j还要再加一个slf4j呢?slf4j里面有一个{},这个叫什么呢?通配符。后面接的参数可以自动补入。例如:
logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
这段代码后面的t与oldT就会根据参数顺序依次补入到前面的{}中,可以减少程序因为字符串拼接而造成堆内存的泄露。
相关的引用包有:
log4j-api:log4j对外提供的接口
log4j-core:log4j对api的具体实现,也叫核心包
log4j-web: 针对于java web的应用
slf4j-api:slf4对外提供的接口。slf4j它实质就是提供一个接口可以支持不同的日志系统。所以它只有这个api没有一般的core包
log4j-slf4j-impl:用于与slf4进行连接。
其中,有一个包与log4j-slf4j-impl非常相像,名字为slf4j-log4j12的包,这两个反编译后发现还是有一些类的完全一致的,但是有一些又不同。所以我个人认为这个有可能是因为不同的需求封装的不同API而已。
我在这里使用log4j-slf4j-impl主要是为了兼容。也没有过多去深究。理由很简单:log4j-slf4j-impl与slf4j-log4j1都放在maven依赖里,看一下日志文件哪个可以打出来就用哪个。
下面是maven里的依赖(亲测有效)
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.9.1</version>
</dependency>
在程序中编写log4j2.xml文件,然后在web.xml里配置
<!--log4j2-->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/conf/log4j2.xml</param-value>
</context-param>
在程序中引用:
Logger log = LoggerFactory.getLogger(controller.class);
log.debug("XXX")
就可以在log4j2.xml文件中指定的路径下访问到对应的日志输出。
遗留问题:
- log4j各种层级结构是怎么样的?
- slf4j各种层级结构的含义?