我们前面已经讲过了 SLF4J 的两种用法:SLF4J+Log4J 和 SLF4J+Logback,那是在比较理想的情况下,所用组件只使用了 SLF4J 这一种统一日志框架的时候。可是 JCL 一直影响深远,SLF4J 渐入佳境的时个,在你的项目中很可能所用的组件,它们分别用了 JCL 和 SLF4J 两种组件。比如说在项目中用了 Hibernate 3.5 和 Struts,或其他 Apache 的一些开源组件,你大约也不想用了 SLF4J 的组件日志信息输出到 A 处,用了 JCL 的组件日志输出到 B 处,那你自己写的代码中的日志信息该往哪儿写呢?
中国人一直都愿追求大一统,不喜欢城邦制的便于分而治之。但说到日志输出还是得统一到单一通道中来,一方面多个通道浪费资源,另方面也便于配置和管理。那么既然 SLF4J 是趋势,当 SLF4J 和 JCL 被丢到一个坛子里,首先会让 SLF4J 为主,JCL 为辅,也就是要把 JCL 桥接到 SLF4J 上来,通过 SLF4J 统一输出日志信息。于是也就是这篇要介绍的 SLF4J 使用模式:JCL-Over-SLF4J+SLF4J。
从前面对 SLF4J 的认识可知,即使把 JCL 转嫁到 SLF4J,还是无法输出日志,还需要一种日志实现,下层该用 Log4J 还得用 Log4J,想用 Logback 还是要用 Logback。所以到了 SLF4J 后还得往下走,也就是前面那两条路 SLF4J+Log4J 和 SLF4J+Logback,本篇使用 SLF4J 的模式具体就要分为:
JCL-Over-SLF4J+SLF4J+Log4J 和 JCL-Over-SLF4J+SLF4J+Logback,这两种实现方式差不多。只是分别用的 jar 包和配置文件不同,SLF4J+Log4J 和 SLF4J+Logback 原来要哪些文件现在还是需要那些文件,只是都要加上 jcl-over-slf4j-1.5.11.jar 包。这里说明 JCL-Over-SLF4J+SLF4J+Logback 的方式。
需要的配置文件和组件包,下面四个 jar 文件和一个 xml文件都是要放在项目的 ClassPath 上。
1. slf4j-api-1.5.11.jar
2. logback-core-0.9.20.jar
3. logback-classic-0.9.20.jar
4. logback.xml 或 logback-test.xml
5. jcl-over-slf4j-1.5.11.jar
第 1 和第 5 个包在 http://www.slf4j.org/download.html 处下载,第二第三个包在 http://logback.qos.ch/download.html 下载,可能包文件名中的版本号有些差异。
下面是一个最简单的 logback.xml 文件内容
01
02
03
04
05
06
07
08
09
10
11
12
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< configuration >
< appender name = "stdout" class = "ch.qos.logback.core.ConsoleAppender" >
< encoder charset = "GBK" >
< pattern >[Consociate] %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</ pattern >
</ encoder >
</ appender >
< root level = "DEBUG" >
< appender-ref ref = "stdout" />
</ root >
</ configuration >
|
为了看看效果,我们在输入的 pattern 中加入了 [Consociate],来检验是否统一到单一的日志通道中去了。
使用 了 JCL 和 SLF4J 的代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package com.unmi;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestJCLOverSlf4j {
//SLF4J 的 Logger
private static final Logger logger = LoggerFactory.getLogger( "From SLF4J" );
//JCL 的 Log
private static final Log log = LogFactory.getLog( "From JCL" );
//分别用上面的 logger 和 log 输出日志,从输出可以看到它们统一到一个通道中了
public static void main(String[] args) {
logger.info( "Hello {}" , "From SLF4J" );
log.info( "Hello From JCL" );
}
} |
我们在上面代码中,既使用了 JCL 统一日志框架,也使用了 SLF4J 的统一日志框架。要注意一点,从 JCL 桥接过来的 log 不能输出参数化消息了。上面代码使用了 org.apache.commons.logging.Log,import org.apache.commons.logging.LogFactory,但你却用不着引入 commons-logging.jar 包。
执行上面的代码,看到输出:
[Consociate] 23:19:39.890 [main] INFO From SLF4J - Hello From SLF4J
[Consociate] 23:19:39.921 [main] INFO From JCL - Hello From JCL
很明显示 JCL 框架和 SLF4J 框架的日志输出都统一到了一个通道中来了,为什么呢? SLF4J 使用的是 Logback 输出的信息,这一点没问题的,而 JCL 是不认识 Logback 的,所以 JCL 框架的输出必然是绕道到 SLF4J,最后也是由 Logback 输出的。
实现分析:
我们打开 jcl-over-slf4j-1.5.11.jar,看到里面有两个包 org.apache.commons.logging 和 org.apache.commons.logging.impl,并有相应的类,这就是为什么,虽然在代码中有:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
却不用把 commons-logging.jar 包引入到类路径上的原因。
再深入下 jcl-over-slf4j-1.5.11.jar,看到其中还有个文件 /META-INF/services/org.apache.commons.logging.LogFactory,内容为:
org.apache.commons.logging.impl.SLF4JLogFactory
# Axis gets at JCL through its own mechanism as defined by Commons Discovery, which
# in turn follows the instructions found at:
# http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service Provider
JCL 运行时使用了 SLF4JLogFactory,从而完成了 JCL 的日志实现委托给了 SLF4J,再由 SLF4J 进一步完成具体的日志输出。
采用 JCL-Over-SLF4J+SLF4J+Log4J 使用模式也是相似的,这里就不详述了。总结下就是 JCL 把 SLF4J 当作它的日志实现。
再来想象个问题:如果我们把这两个包 jcl-over-slf4j-1.5.11.jar 和 slf4j-jcl-1.5.11.jar 都放到 ClassPath 下会有什么情况呢?JCL 代理给 SLF4J,SLF4J 又绑定到 JCL,对了,死循环,StackOverFlow 错误:
SLF4J: Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
java.lang.ExceptionInInitializerError
at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:82)
at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:51)
at org.slf4j.LoggerFactory.getSingleton(LoggerFactory.java:230)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:121)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:112)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:275)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:248)
at com.unmi.TestJCLOverSlf4j.<clinit>(TestJCLOverSlf4j.java:10)
Caused by: java.lang.IllegalStateException: Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError. See alsohttp://www.slf4j.org/codes.html#jclDelegationLoop for more details.
at org.slf4j.impl.JCLLoggerFactory.<clinit>(JCLLoggerFactory.java:64)
... 8 more
Exception in thread "main"
相关推荐
《jcl-over-slf4j-1.6.0.jar:日志框架转换与使用场景实例解析》 在软件开发中,日志记录是不可或缺的一部分,它帮助开发者追踪程序运行状态,定位错误和异常。在Java世界里,我们常常会遇到多种日志框架并存的情况...
jcl-over-slf4j-1.6.1.jar log4j-1.2.8.jar logback-access-0.9.24.jar logback-classic-0.9.24.jar logback-core-0.9.24.jar servlet-api.jar slf4j-1.6.1+logback-0.9.24.rar slf4j-api-1.6.1.jar
通过使用SLF4J,开发者可以在不修改代码的情况下,选择合适的底层日志框架,如Logback、Log4j或Java内置的日志系统。这样可以使得日志配置更加灵活,同时在不同环境中保持一致的代码基础。 1. **SLF4J API**:SLF4J...
压缩包中的`jcl-over-slf4j-1.5.10-sources.jar`是一个桥接器,它的作用是将使用Jakarta Commons Logging(JCL)的日志调用重定向到SLF4J。这是因为一些老的库可能使用了JCL,但SLF4J并不直接支持它,所以引入这个桥...
commons-logging-1.2.jar、log4j-1.2.17.jar、logback-classic-1.1.2.jar、logback-core-1.1.2.jar、slf4j-api-1.7.12.jar、slf4j-jcl-1.7.12.jar、slf4j-simple-1.7.12.jar
- 可选的适配器JAR,例如:`jcl-over-slf4j-1.4.3.jar` 或 `log4j-over-slf4j-1.4.3.jar`,取决于你的需求。 **示例代码**: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ...
SLF4J-JCL(Jakarta Commons Logging)桥接器是SLF4J的一个组件,它使得那些依赖于Jakarta Commons Logging(JCL)的库能够透明地使用SLF4J。JCL是一个早期的日志接口,许多流行的开源库如Hibernate、Struts等都曾...
- **jcl-over-slf4j.jar**:用于替换Apache Commons Logging。 - **log4j-over-slf4j.jar**:用于替换Log4J,需要注意的是,原有的`log4j.properties`配置文件将不再有效,需要转换为`logback.xml`。 - **jul-to-slf...
使用SLF4J的关键在于,通过在项目中引入`slf4j-api.jar`,然后根据实际需求选择合适的日志实现(如logback或log4j),并通过相应的适配器(如`slf4j-log4j12.jar`)桥接SLF4J接口与具体日志框架。这样,如果将来需要...
<artifactId>jcl-over-slf4j <version>1.7.13 <scope>runtime <groupId>org.apache.logging.log4j <artifactId>log4j-api <version>2.4.1 <groupId>org.apache.logging.log4j <artifactId>log4j-core ...
- **其他绑定**:SLF4J还支持其他日志系统,如log4j-over-slf4j.jar(Log4j到SLF4J的桥接)、jcl-over-slf4j.jar(Jakarta Commons Logging到SLF4J的桥接)等。 3. **SLF4J的优势** - **灵活性**:SLF4J允许在不...
2. **添加桥接器**:引入`slf4j-jcl`(Jakarta Commons Logging桥接器)的jar文件,这会让commons-logging的调用转到SLF4J。 3. **配置SLF4J**:在项目中添加Logback的配置文件(例如`logback.xml`),以控制日志的...
配置SLF4J的方式通常是通过配置文件,例如Logback的配置文件`logback.xml`,在这里可以指定日志级别、输出目的地、格式等。对于其他绑定,如Log4j,需要对应的配置文件(如`log4j.properties`或`log4j.xml`)。 ...
NULL 博文链接:https://tristan-s.iteye.com/blog/1966020
JCL-over-SLF4J的作用是将依赖JCL的日志调用重定向到SLF4J,这样可以让这些库无缝地与SLF4J集成,利用SLF4J提供的日志服务。 **整合使用** 在实际项目中,这三个JAR包的组合意味着开发者可以利用Mina框架创建网络...
通过使用适当的桥接库,如 jcl104-over-slf4j.jar,可以轻松地将现有的JCL或log4j日志调用转换为SLF4J,从而方便地迁移到logback。 5. **JUL支持**:如果你的项目中已经使用了JUL,logback 也提供了直接支持,通过...
7. **迁移友好**:通过 SLF4J,可以轻松地将现有的 JUL、JCL 或 log4j 日志调用迁移到 LogBack,无需更改一行代码。只需使用适当的桥接器,LogBack 就能接管这些日志系统。 8. **API 简洁性**:LogBack 的 API 设计...
- 其他可能需要的依赖,例如 JCL-over-SLF4J(Jakarta Commons Logging)的桥接器,以便将使用 JCL 的库的日志输出重定向到 SLF4J。 **4. 配置与使用** 在使用 Logback 时,你需要创建一个 `logback.xml` 或 `...
---10-slf4j与其他日志的配合与总结.mp4 ---11-log4j2的配置与日志发展历程总结.mp4 ---12-日志组件配置概述.mp4 ---13-jul配置文件与级别.mp4 ---14-jul打印级别与其他配置项.mp4 ---15-log4j配置文件与配置项.mp4 ...