文章目录
梳理Java当前主流的日志体系
当前主流的日志框架有
JUL
: Java.util.logging ,JDK 自带的日志实现
JCL
: 全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging", 一套日志门面 ,只支持JUL
和 Log4j
。
SLF4J
: 全称为"Simple Logging Facade For Java",一套日志门面,支持几乎当前所有主流的日志框架。
Log4j
: Log for Java
Log4j2
: Log4j
的升级 ,Log4j2
和Log4j
是一个作者,只不过Log4j2
是重新架构的一款日志组件,他抛弃了之前log4j
的不足,以及吸取了优秀的Logback
的设计,实现了SLF4J
,当然也有自己的门面Log4j2-API
。
Logback
: Log4j
的升级 ,实现了SLF4J
。
日志体系分为两类,一类是日志实现,一类是日志门面。可以简单理解为门面就是接口,制定了一套日志处理的标准和规范,而实现就是接口的具体实现。
下面对不同的日志框架,在Spring Boot环境下进行测试。
Demo 项目源码: java-log
Spring Boot背景下的各日志框架的测试
Spring Boot 版本: 2.7.9
JDK 版本:1.8
因为Spring Boot默认使用Logback
日志框架,因此未来避免干扰,默认都排除掉spring-boot-starter-logging
包
JCL demo
测试使用JCL输出日志
JCL
的配置文件为commons-logging.properties
。
引入依赖
<!--添加jcl 依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
Spring Boot环境下的默认处理
在Spring Boot环境中,默认引入了Spring-jcl
包,在这个包中有一个Jcl
的适配器org.apache.commons.logging.LogAdapter
在这个适配器里会根据当前运行环境,加载默认的Jcl
处理器
static {
if (isPresent("org.apache.logging.log4j.spi.ExtendedLogger")) {
if (isPresent("org.apache.logging.slf4j.SLF4JProvider") && isPresent("org.slf4j.spi.LocationAwareLogger")) {
logApi = LogAdapter.LogApi.SLF4J_LAL;
} else {
logApi = LogAdapter.LogApi.LOG4J;
}
} else if (isPresent("org.slf4j.spi.LocationAwareLogger")) {
logApi = LogAdapter.LogApi.SLF4J_LAL;
} else if (isPresent("org.slf4j.Logger")) {
logApi = LogAdapter.LogApi.SLF4J;
} else {
logApi = LogAdapter.LogApi.JUL;
}
}
因此默认的输出使用的JUL
[2023-10-26 11:27:44.907] - 45884 信息 [main] --- com.feiyizhan.LogJclTests: 这是info日志...
[2023-10-26 11:27:44.915] - 45884 警告 [main] --- com.feiyizhan.LogJclTests: 这是warn日志...
[2023-10-26 11:27:44.920] - 45884 严重 [main] --- com.feiyizhan.LogJclTests: 这是error日志...
[2023-10-26 11:27:44.920] - 45884 信息 [main] --- com.feiyizhan.LogJclTests: private static class org.apache.commons.logging.LogAdapter$JavaUtilLog
使用Log4j
处理
引入依赖
<!--引入Log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
因为Spring
有自己的Spring-jcl
,这个是包是处理JCL
转SLF4J
的,因此如果要修改为log4j
,则需要排除掉这个包的依赖。
再补充log4j
的配置文件log4j.properties
就可以使用log4j
输出日志了。
当然也可以在commons-logging.properties
强制指定Log4j
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger
2023-10-26 11:38:12 DEBUG (com.feiyizhan.LogJclTests:25) - 这是debug日志...
2023-10-26 11:38:12 INFO (com.feiyizhan.LogJclTests:27) - 这是info日志...
2023-10-26 11:38:12 WARN (com.feiyizhan.LogJclTests:28) - 这是warn日志...
2023-10-26 11:38:12 ERROR (com.feiyizhan.LogJclTests:29) - 这是error日志...
2023-10-26 11:38:12 INFO (com.feiyizhan.LogJclTests:30) - public class org.apache.commons.logging.impl.Log4JLogger
同时有Log4j
依赖时,强制使用JUL
处理
在commons-logging.properties
中强制指定JUL
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Jdk14Logger
[2023-10-26 11:41:13.173] - 46792 信息 [main] --- com.feiyizhan.LogJclTests: 这是info日志...
[2023-10-26 11:41:13.175] - 46792 警告 [main] --- com.feiyizhan.LogJclTests: 这是warn日志...
[2023-10-26 11:41:13.175] - 46792 严重 [main] --- com.feiyizhan.LogJclTests: 这是error日志...
[2023-10-26 11:41:13.177] - 46792 信息 [main] --- com.feiyizhan.LogJclTests: public class org.apache.commons.logging.impl.Jdk14Logger
JUL demo
测试使用JUL
输出日志
单机环境
在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
单机环境下测试结果:
十月 19, 2023 6:26:09 下午 com.feiyizhan.LogJulTests test_default_log
信息: 这是info日志...
十月 19, 2023 6:26:09 下午 com.feiyizhan.LogJulTests test_default_log
信息: public class java.util.logging.Logger
Spring Boot 环境
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
Spring Boot 环境下测试结果
[2023-10-20 11:49:06.913] - 38764 信息 [main] --- com.feiyizhan.LogJulSpringBootTests: 这是info日志...
[2023-10-20 11:49:06.943] - 38764 信息 [main] --- com.feiyizhan.LogJulSpringBootTests: public class java.util.logging.Logger
Log4j demo
默认日志配置文件: log4j.properties
引入依赖
<!--引入Log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
JCL 门面
Spring 默认引入了JCL
和SLF4j
两个门面,因此如果只测试JCL
就需要排除slf4j-api
JCL 门面:
2023-10-26 14:59:46 DEBUG (com.feiyizhan.LogLog4jTests:18) - 这是debug日志...
2023-10-26 14:59:46 INFO (com.feiyizhan.LogLog4jTests:20) - 这是info日志...
2023-10-26 14:59:46 WARN (com.feiyizhan.LogLog4jTests:21) - 这是warn日志...
2023-10-26 14:59:46 ERROR (com.feiyizhan.LogLog4jTests:22) - 这是error日志...
2023-10-26 14:59:46 INFO (com.feiyizhan.LogLog4jTests:23) - public class org.apache.log4j.Logger
Log4j2 demo
Log4j2
有自己的API,因此可以不使用其他的门面来完成日志输出
可以直接在application.properties
配置。
也可以使用log4j2.xml
配置,但需要在application.properties
指定配置文件
logging.config=classpath:log4j2.xml
引入依赖
<!--Log4j2相关的依赖包-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
使用Log4j2 API
Spring 默认引入了JCL
和SLF4j
两个门面,因此如果只测试Log4j2
就需要排除spring-jcl
和slf4j-api
,
但由于Spring Boot项目内部有使用JCL
门面的日志输出,因此需要再额外引入JCL
的门面包commons-logging
<!--添加jcl 依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
只是这样会原本使用JCL
输出的日志将无法输出,因为没有具体的JCL
实现了。这个问题后面解决。
spring-jcl
是Spring自己实现的jcl
重定向到slf4j
的包。
日志输出:
2023-10-26 15:58:20.652 TRACE 46532 --- [ main] c.f.LogLog4j2Tests : 这是trace日志...
2023-10-26 15:58:20.654 DEBUG 46532 --- [ main] c.f.LogLog4j2Tests : 这是debug日志...
2023-10-26 15:58:20.655 INFO 46532 --- [ main] c.f.LogLog4j2Tests : 这是info日志...
2023-10-26 15:58:20.655 WARN 46532 --- [ main] c.f.LogLog4j2Tests : 这是warn日志...
2023-10-26 15:58:20.655 ERROR 46532 --- [ main] c.f.LogLog4j2Tests : 这是error日志...
2023-10-26 15:58:20.656 INFO 46532 --- [ main] c.f.LogLog4j2Tests : 这是info日志...test
2023-10-26 15:58:20.657 INFO 46532 --- [ main] c.f.LogLog4j2Tests : public class org.apache.logging.log4j.core.Logger
Logback Demo
配置文件为:logback.xml
引入依赖
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
logback-classic
是包含slf4j
门面和logback
给slf4j
门面的实现,因此引入这个一个包就可以了。
注: JDK8 只能使用1.3及以下版本,1.4以上版要求JDK11,详情参考:https://logback.qos.ch/news.html
Spring 默认引入了JCL
和SLF4j
两个门面,因此如果只测试SLF4j
就需要排除spring-jcl
,
但由于Spring Boot项目内部有使用JCL
门面的日志输出,因此需要再额外引入JCL
的门面包commons-logging
<!--添加jcl 依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
只是这样会原本使用JCL
输出的日志将无法输出,因为没有具体的JCL
实现了。这个问题后面解决。
spring-jcl
是Spring自己实现的jcl
重定向到slf4j
的包。
日志输出:
16:32:07.122 [main] TRACE com.feiyizhan.LogBackTests - 这是trace日志...
16:32:07.124 [main] DEBUG com.feiyizhan.LogBackTests - 这是debug日志...
16:32:07.124 [main] INFO com.feiyizhan.LogBackTests - 这是info日志...
16:32:07.124 [main] WARN com.feiyizhan.LogBackTests - 这是warn日志...
16:32:07.124 [main] ERROR com.feiyizhan.LogBackTests - 这是error日志...
16:32:07.124 [main] INFO com.feiyizhan.LogBackTests - 这是info日志...test
16:32:07.126 [main] INFO com.feiyizhan.LogBackTests - public final class ch.qos.logback.classic.Logger
SLF4J demo
测试只有slf4j-api 接口包,没有具体实现包的场景
引入依赖
<!--添加Slfj 依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
Spring 默认引入了JCL
和SLF4j
两个门面,因此如果只测试SLF4j
就需要排除spring-jcl
,
但由于Spring Boot项目内部有使用JCL
门面的日志输出,因此需要再额外引入JCL
的门面包commons-logging
<!--添加jcl 依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
只是这样会原本使用JCL
输出的日志将无法输出,因为没有具体的JCL
实现了。这个问题后面解决。
spring-jcl
是Spring自己实现的jcl
重定向到slf4j
的包。
输出结果
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J simple Demo
Spring Boot环境下,简单配置slf4j-simple
方式就是在application.properties
增加logging.
前缀的配置
例如
logging.level.root = info
更详细的配置可以增加simplelogger.properties
配置文件来配置
默认的日志输出格式相当于log4j
的 "%r [%t] %level %logger - %m%n"
引入对应依赖
<!--添加Slfj 依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
Spring 默认引入了JCL
和SLF4j
两个门面,因此如果只测试SLF4j
就需要排除spring-jcl
,
但由于Spring Boot项目内部有使用JCL
门面的日志输出,因此需要再额外引入JCL
的门面包commons-logging
<!--添加jcl 依赖-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
只是这样会原本使用JCL
输出的日志将无法输出,因为没有具体的JCL
实现了。这个问题后面解决。
spring-jcl
是Spring自己实现的jcl
重定向到slf4j
的包。
日志输出:
2023-10-26 16:43:58.706 [main] DEBUG Slf4jSimpleTests - 这是debug日志...
2023-10-26 16:43:58.709 [main] INFO Slf4jSimpleTests - 这是info日志...
2023-10-26 16:43:58.710 [main] WARN Slf4jSimpleTests - 这是warn日志...
2023-10-26 16:43:58.710 [main] ERROR Slf4jSimpleTests - 这是error日志...
2023-10-26 16:43:58.710 [main] INFO Slf4jSimpleTests - 这是info日志...test
2023-10-26 16:43:58.710 [main] INFO Slf4jSimpleTests - public class org.slf4j.simple.SimpleLogger
SLF4J JUL binding demo
测试Slf4j
binding (桥接到 Jul
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用Jul
输出日志
要实现这个效果就必须引入对应日志框架的Slf4j
的Over包,将日志重定向到Slf4j
。但由于Slf4j
并没有一个具体的日志实现,所以还得找一个具体的日志实现,这个demo选择的是Jul
作为最终的日志实现。
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
Logback
本身就支持并使用了slf4j
门面 ,没有要Over
也不需要Over
,因此不参与本测试。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
然后引入jcl-over-slf4j
包就可以,当然也可以用spring-jcl
,效果一样。
Log4j
Over 处理
Log4j
除了需要引入log4j-over-slf4j
包外,还要排除掉log4j
本身的依赖包,否则Over是无效的。
<!--引入Log4j-->
<!-- <dependency>-->
<!-- <groupId>log4j</groupId>-->
<!-- <artifactId>log4j</artifactId>-->
<!-- <version>1.2.17</version>-->
<!-- </dependency>-->
Log4j2
Over 处理
log4j2
引入log4j-to-slf4j
这个包。
还需要排除log4j-core
包,当然如果同时存在logback-classic
则不排除也可以正常运行,否则会抛出异常org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
。因为Spring 默认会优先加载Logback的LoggingSystem
的一个实现LogbackLoggingSystem
,当没有的时候才会选择Log4J2LoggingSystem
,但当没有Logback
实现,并且存在log4j-core
时,
将会使用Log4J2LoggingSystem
作为日志的实现,其实也就是一个动态的加载日志实现系统的处理。但log4j-core
不能直接转换到Slf4j
,因此才会抛出上面的异常。
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-core</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!-- </dependency>-->
Jul
Over 处理
本Demo是最终是使用Jul
输出日志,因此不能再把Jul
Over
掉了,因此不做Over
处理。排除jul-to-slf4j
依赖。
<!-- jul over slf4j -->
<!--<dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>jul-to-slf4j</artifactId>-->
<!-- <version>${slf4j.version}</version>-->
<!--</dependency>-->
注意
jul-to-slf4j
和slf4j-jdk14
不能同时引入,因为一个是将Jul
重定向到slf4j
,另一个是将slf4j
的日志输出使用Jul
来输出。
j和
slf4j-jdk14不能同时引入,因为一个是将
Jul重定向到
slf4j,另一个是将
slf4j的日志输出使用
Jul`来输出。
SLF4J
Binding Jul
的处理
引入slf4j
的Jul
实现包slf4j-jdk14
<!-- jul binding slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j.version}</version>
</dependency>
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
。
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件logging.config=classpath:logging.properties
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出,JCL
在没有默认实现的时候,使用的就是JUL
实现,但在这里有Log4j
的实现,因此使用的是Log4j
的实现。
2023-11-23 14:06:00 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-11-23 14:06:00 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-11-23 14:06:00 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-11-23 14:06:00 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-11-23 14:06:00 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
十一月 23, 2023 2:06:00 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
十一月 23, 2023 2:06:00 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2023-11-23 14:06:00 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-11-23 14:06:00 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-11-23 14:06:00 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-11-23 14:06:00 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-11-23 14:06:00 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
14:06:00.471 [main] ERROR com.feiyizhan.LogLog4j2Tests - LogLog4j2Tests 这是error日志...
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
[2023-11-23 14:22:32.331] - 13660 INFO [main] --- com.feiyizhan.LogJclTests: LogJclTests 这是info日志...
[2023-11-23 14:22:32.331] - 13660 WARNING [main] --- com.feiyizhan.LogJclTests: LogJclTests 这是warn日志...
[2023-11-23 14:22:32.332] - 13660 SEVERE [main] --- com.feiyizhan.LogJclTests: LogJclTests 这是error日志...
[2023-11-23 14:22:32.333] - 13660 INFO [main] --- com.feiyizhan.LogJclTests: LogJclTests public class org.apache.commons.logging.impl.SLF4JLocationAwareLog
[2023-11-23 14:22:32.334] - 13660 INFO [main] --- com.feiyizhan.LogJulTests: LogJulTests 这是info日志...
[2023-11-23 14:22:32.337] - 13660 INFO [main] --- com.feiyizhan.LogJulTests: LogJulTests public class java.util.logging.Logger
[2023-11-23 14:22:32.343] - 13660 INFO [main] --- com.feiyizhan.LogLog4jTests: LogLog4jTests 这是info日志...
[2023-11-23 14:22:32.343] - 13660 WARNING [main] --- com.feiyizhan.LogLog4jTests: LogLog4jTests 这是warn日志...
[2023-11-23 14:22:32.345] - 13660 SEVERE [main] --- com.feiyizhan.LogLog4jTests: LogLog4jTests 这是error日志...
[2023-11-23 14:22:32.346] - 13660 INFO [main] --- com.feiyizhan.LogLog4jTests: LogLog4jTests public class org.apache.log4j.Logger
[2023-11-23 14:22:32.404] - 13660 INFO [main] --- com.feiyizhan.LogLog4j2Tests: LogLog4j2Tests 这是info日志...
[2023-11-23 14:22:32.409] - 13660 WARNING [main] --- com.feiyizhan.LogLog4j2Tests: LogLog4j2Tests 这是warn日志...
[2023-11-23 14:22:32.411] - 13660 SEVERE [main] --- com.feiyizhan.LogLog4j2Tests: LogLog4j2Tests 这是error日志...
[2023-11-23 14:22:32.415] - 13660 INFO [main] --- com.feiyizhan.LogLog4j2Tests: LogLog4j2Tests 这是info日志...test
[2023-11-23 14:22:32.417] - 13660 INFO [main] --- com.feiyizhan.LogLog4j2Tests: LogLog4j2Tests public class org.apache.logging.slf4j.SLF4JLogger
SLF4J simple binding demo
测试slf4j binding (桥接到 Slf4j-simple
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用slf4j-simple
输出日志
要实现这个效果就必须引入对应日志框架的Slf4j
的Over包,将日志重定向到Slf4j
。但由于Slf4j
并没有一个具体的日志实现,
所以还得找一个具体的日志实现,这个demo选择的是slf4j-simple
作为最终的日志实现。
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
Logback
本身就支持并使用了slf4j
门面 ,不需要Over
。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
然后引入jcl-over-slf4j
包就可以,当然也可以用spring-jcl
,效果一样。
Log4j
Over 处理
Log4j
除了需要引入log4j-over-slf4j
包外,还要排除掉log4j
本身的依赖包,否则Over是无效的。
<!--引入Log4j-->
<!-- <dependency>-->
<!-- <groupId>log4j</groupId>-->
<!-- <artifactId>log4j</artifactId>-->
<!-- <version>1.2.17</version>-->
<!-- </dependency>-->
Log4j2
Over 处理
log4j2
引入log4j-to-slf4j
这个包。
还需要排除log4j-core
包,当然如果同时存在logback-classic
则不排除也可以正常运行,否则会抛出异常org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
。因为Spring 默认会优先加载Logback的LoggingSystem
的一个实现LogbackLoggingSystem
,当没有的时候才会选择Log4J2LoggingSystem
,但当没有Logback
实现,并且存在log4j-core
时,
将会使用Log4J2LoggingSystem
作为日志的实现,其实也就是一个动态的加载日志实现系统的处理。但log4j-core
不能直接转换到Slf4j
,因此才会抛出上面的异常。
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-core</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!-- </dependency>-->
Jul
Over 处理
引入jul-to-slf4j
包。
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件
logging.config=classpath:logging.properties
参考https://www.slf4j.org/legacy.html,https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html 文档,修改默认Handlers,否则Over是不生效的。
简单的方法就是在logging.properties
替换handlers =java.util.logging.ConsoleHandler
配置为handlers = org.slf4j.bridge.SLF4JBridgeHandler
注意
jul-to-slf4j
和slf4j-jdk14
不能同时引入,因为一个是将Jul
重定向到slf4j
,另一个是将slf4j
的日志输出使用Jul
来输出。
SLF4J
Binding Slf4j-Simple
的处理
引入slf4j
的Simple
实现包slf4j-simple
<!--添加Slfj Simple依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
Spring Boot环境下,简单配置slf4j-simple
方式就是在application.properties
增加logging.
前缀的配置
例如
logging.level.root = info
更详细的配置可以增加simplelogger.properties
配置文件来配置
默认的日志输出格式相当于log4j
的 "%r [%t] %level %logger - %m%n"
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出。 Spring Boot中当运行环境有Log4j
时,Jcl
的默认使用Log4j
的实现。
2023-11-03 18:38:01 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-11-03 18:38:01 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-11-03 18:38:01 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-11-03 18:38:01 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-11-03 18:38:01 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
十一月 03, 2023 6:38:01 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
十一月 03, 2023 6:38:01 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2023-11-03 18:38:01 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-11-03 18:38:01 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-11-03 18:38:01 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-11-03 18:38:01 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-11-03 18:38:01 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
2023-11-03 18:38:02.008 [main] DEBUG LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是debug日志...
2023-11-03 18:38:02.010 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是info日志...
2023-11-03 18:38:02.010 [main] WARN LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是warn日志...
2023-11-03 18:38:02.010 [main] ERROR LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是error日志...
2023-11-03 18:38:02.010 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是info日志...test
2023-11-03 18:38:02.010 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests public class org.slf4j.simple.SimpleLogger
18:38:02.022 [main] ERROR com.feiyizhan.LogLog4j2Tests - LogLog4j2Tests 这是error日志...
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
2023-11-03 18:39:39.271 [main] DEBUG LogJclTests - LogJclTests 这是debug日志...
2023-11-03 18:39:39.271 [main] INFO LogJclTests - LogJclTests 这是info日志...
2023-11-03 18:39:39.271 [main] WARN LogJclTests - LogJclTests 这是warn日志...
2023-11-03 18:39:39.271 [main] ERROR LogJclTests - LogJclTests 这是error日志...
2023-11-03 18:39:39.271 [main] INFO LogJclTests - LogJclTests public class org.apache.commons.logging.impl.SLF4JLog
2023-11-03 18:39:39.274 [main] INFO LogJulTests - LogJulTests 这是info日志...
2023-11-03 18:39:39.274 [main] INFO LogJulTests - LogJulTests public class java.util.logging.Logger
2023-11-03 18:39:39.277 [main] DEBUG LogLog4jTests - LogLog4jTests 这是debug日志...
2023-11-03 18:39:39.277 [main] INFO LogLog4jTests - LogLog4jTests 这是info日志...
2023-11-03 18:39:39.277 [main] WARN LogLog4jTests - LogLog4jTests 这是warn日志...
2023-11-03 18:39:39.277 [main] ERROR LogLog4jTests - LogLog4jTests 这是error日志...
2023-11-03 18:39:39.277 [main] INFO LogLog4jTests - LogLog4jTests public class org.apache.log4j.Logger
2023-11-03 18:39:39.278 [main] DEBUG LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是debug日志...
2023-11-03 18:39:39.278 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是info日志...
2023-11-03 18:39:39.278 [main] WARN LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是warn日志...
2023-11-03 18:39:39.278 [main] ERROR LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是error日志...
2023-11-03 18:39:39.278 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests 这是info日志...test
2023-11-03 18:39:39.278 [main] INFO LogSlf4jSimpleTests - LogSlf4jSimpleTests public class org.slf4j.simple.SimpleLogger
2023-11-03 18:39:39.378 [main] DEBUG LogLog4j2Tests - LogLog4j2Tests 这是debug日志...
2023-11-03 18:39:39.379 [main] INFO LogLog4j2Tests - LogLog4j2Tests 这是info日志...
2023-11-03 18:39:39.379 [main] WARN LogLog4j2Tests - LogLog4j2Tests 这是warn日志...
2023-11-03 18:39:39.381 [main] ERROR LogLog4j2Tests - LogLog4j2Tests 这是error日志...
2023-11-03 18:39:39.389 [main] INFO LogLog4j2Tests - LogLog4j2Tests 这是info日志...test
2023-11-03 18:39:39.390 [main] INFO LogLog4j2Tests - LogLog4j2Tests public class org.apache.logging.slf4j.SLF4JLogger
SLF4J Jcl binding demo
测试Slf4j
binding (桥接到 Jcl
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用Jcl
输出日志
要实现这个效果就必须引入对应日志框架的Slf4j
的Over包,将日志重定向到Slf4j
。但由于Slf4j
并没有一个具体的日志实现,所以还得找一个具体的日志实现,这个demo选择的是Jcl
作为最终的日志实现。
而Jcl
本身也是一个日志门面,需要配合具体的实现来做日志输出,这个demo使用Log4j
作为Jcl
的日志实现。
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
Logback
本身就支持并使用了slf4j
门面 ,没有要Over
也不需要Over
,因此不参与本测试。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
本demo最终使用Jcl
作为输出,因此排除Jcl
的Over
包
<!-- jcl over slf4j -->
<!--<dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>jcl-over-slf4j</artifactId>-->
<!-- <version>${slf4j.version}</version>-->
<!--</dependency>-->
Log4j
Over 处理
本demo 最终使用Log4j
做Jcl
的实现,不能再对Log4j
做Over
,因此需要排除log4j-over-slf4j
包。
<!-- lo4j over slf4j -->
<!--<dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>log4j-over-slf4j</artifactId>-->
<!-- <version>${slf4j.version}</version>-->
<!--</dependency>-->
Log4j2
Over 处理
log4j2
引入log4j-to-slf4j
这个包。
还需要排除log4j-core
包,当然如果同时存在logback-classic
则不排除也可以正常运行,否则会抛出异常org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
。因为Spring 默认会优先加载Logback的LoggingSystem
的一个实现LogbackLoggingSystem
,当没有的时候才会选择Log4J2LoggingSystem
,但当没有Logback
实现,并且存在log4j-core
时,
将会使用Log4J2LoggingSystem
作为日志的实现,其实也就是一个动态的加载日志实现系统的处理。但log4j-core
不能直接转换到Slf4j
,因此才会抛出上面的异常。
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-core</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!-- </dependency>-->
Jul
Over 处理
引入jul-to-slf4j
包。
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件
logging.config=classpath:logging.properties
参考https://www.slf4j.org/legacy.html,https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html 文档,修改默认Handlers,否则Over是不生效的。
简单的方法就是在logging.properties
替换handlers =java.util.logging.ConsoleHandler
配置为handlers = org.slf4j.bridge.SLF4JBridgeHandler
注意
jul-to-slf4j
和slf4j-jdk14
不能同时引入,因为一个是将Jul
重定向到slf4j
,另一个是将slf4j
的日志输出使用Jul
来输出。
引入 SLF4J
binding 到 jcl
的包
<!-- SLF4J binding Jcl -->->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>${slf4j.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出。
2023-11-23 15:15:59 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-11-23 15:15:59 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-11-23 15:15:59 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-11-23 15:15:59 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-11-23 15:15:59 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
十一月 23, 2023 3:15:59 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
十一月 23, 2023 3:15:59 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2023-11-23 15:15:59 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-11-23 15:15:59 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-11-23 15:15:59 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-11-23 15:15:59 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-11-23 15:15:59 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
15:15:59.124 [main] ERROR com.feiyizhan.LogLog4j2Tests - 这是error日志...
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
2023-11-23 15:20:24 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-11-23 15:20:24 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-11-23 15:20:24 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
2023-11-23 15:20:24 INFO (com.feiyizhan.LogJulTests:338) - LogJulTests 这是info日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogJulTests:338) - LogJulTests public class java.util.logging.Logger
2023-11-23 15:20:24 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-11-23 15:20:24 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-11-23 15:20:24 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
2023-11-23 15:20:24 DEBUG (com.feiyizhan.LogLog4j2Tests:242) - 这是debug日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogLog4j2Tests:338) - 这是info日志...
2023-11-23 15:20:24 WARN (com.feiyizhan.LogLog4j2Tests:433) - 这是warn日志...
2023-11-23 15:20:24 ERROR (com.feiyizhan.LogLog4j2Tests:528) - 这是error日志...
2023-11-23 15:20:24 INFO (com.feiyizhan.LogLog4j2Tests:338) - 这是info日志...test
2023-11-23 15:20:24 INFO (com.feiyizhan.LogLog4j2Tests:338) - public class org.apache.logging.slf4j.SLF4JLogger
版本冲突的问题
slf4j-jcl
最高只支持slf4j
1.7.x
版本,因此必须要将slf4j 降到 1.7.x版本才能使用
异常信息如下:
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions 1.7.x or earlier.
SLF4J: Ignoring binding found at [jar:file:/D:/repository/org/slf4j/slf4j-jcl/1.7.36/slf4j-jcl-1.7.36.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See https://www.slf4j.org/codes.html#ignoredBindings for an explanation.
SLF4j Log4j2 binding demo
测试Slf4j binding (桥接到 Log4j2
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用Log4j2
输出日志
要实现这个效果就必须引入对应日志框架的Slf4j
的Over包,将日志重定向到Slf4j
。但由于Slf4j
并没有一个具体的日志实现,所以还得找一个具体的日志实现,这个demo选择的是Log4j2
作为最终的日志实现。
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
Logback
本身就支持并使用了slf4j
门面 ,没有要Over
也不需要Over
,因此不参与本测试。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
然后引入jcl-over-slf4j
包就可以,当然也可以用spring-jcl
,效果一样。
Log4j
Over 处理
Log4j
除了需要引入log4j-over-slf4j
包外,还要排除掉log4j
本身的依赖包,否则Over是无效的。
<!--引入Log4j-->
<!-- <dependency>-->
<!-- <groupId>log4j</groupId>-->
<!-- <artifactId>log4j</artifactId>-->
<!-- <version>1.2.17</version>-->
<!-- </dependency>-->
Log4j2
Over 处理
本Demo是最终是使用log4j2
输出,因此不能再把Log4j2
Over掉了,因此不做Over处理。
<!-- LOG4J2 over SLF4j -->
<!--<dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-to-slf4j</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!--</dependency>-->
Jul
Over 处理
引入jul-to-slf4j
包。
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件
logging.config=classpath:logging.properties
参考https://www.slf4j.org/legacy.html,https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html 文档,修改默认Handlers,否则Over是不生效的。
简单的方法就是在logging.properties
替换handlers =java.util.logging.ConsoleHandler
配置为handlers = org.slf4j.bridge.SLF4JBridgeHandler
Slf4j
Binding Log4j2
的处理
引入slf4j
的Log4j2
实现包log4j-slf4j-impl
<!-- slf4j binding Log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件
logging.config=classpath:logging.properties
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出,JCL
在有Log4j
的时候,使用的就是Log4j
实现。
2023-10-27 14:26:29 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-10-27 14:26:29 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-10-27 14:26:29 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-10-27 14:26:29 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-10-27 14:26:29 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
十月 27, 2023 2:26:29 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
十月 27, 2023 2:26:29 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2023-10-27 14:26:29 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-10-27 14:26:29 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-10-27 14:26:29 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-10-27 14:26:29 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-10-27 14:26:29 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
[2023-10-27 14:26:29.360] [] [main] INFO : [c.f.LogLog4j2Tests:19] - 这是info日志...
[2023-10-27 14:26:29.363] [] [main] WARN : [c.f.LogLog4j2Tests:20] - 这是warn日志...
[2023-10-27 14:26:29.363] [] [main] ERROR: [c.f.LogLog4j2Tests:21] - 这是error日志...
[2023-10-27 14:26:29.377] [] [main] INFO : [c.f.LogLog4j2Tests:22] - 这是info日志...test
[2023-10-27 14:26:29.377] [] [main] INFO : [c.f.LogLog4j2Tests:23] - public class org.apache.logging.slf4j.Log4jLogger
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
[2023-10-27 14:25:05.314] [] [main] INFO : [c.f.LogJclTests:23] - LogJclTests 这是info日志...
[2023-10-27 14:25:05.314] [] [main] WARN : [c.f.LogJclTests:24] - LogJclTests 这是warn日志...
[2023-10-27 14:25:05.314] [] [main] ERROR: [c.f.LogJclTests:25] - LogJclTests 这是error日志...
[2023-10-27 14:25:05.314] [] [main] INFO : [c.f.LogJclTests:26] - LogJclTests public class org.apache.commons.logging.impl.SLF4JLocationAwareLog
[2023-10-27 14:25:05.316] [] [main] INFO : [c.f.LogJulTests:19] - LogJulTests 这是info日志...
[2023-10-27 14:25:05.316] [] [main] INFO : [c.f.LogJulTests:20] - LogJulTests public class java.util.logging.Logger
[2023-10-27 14:25:05.319] [] [main] INFO : [c.f.LogLog4jTests:23] - LogLog4jTests 这是info日志...
[2023-10-27 14:25:05.320] [] [main] WARN : [c.f.LogLog4jTests:24] - LogLog4jTests 这是warn日志...
[2023-10-27 14:25:05.320] [] [main] ERROR: [c.f.LogLog4jTests:25] - LogLog4jTests 这是error日志...
[2023-10-27 14:25:05.320] [] [main] INFO : [c.f.LogLog4jTests:26] - LogLog4jTests public class org.apache.log4j.Logger
[2023-10-27 14:25:05.322] [] [main] INFO : [c.f.LogLog4j2Tests:19] - 这是info日志...
[2023-10-27 14:25:05.322] [] [main] WARN : [c.f.LogLog4j2Tests:20] - 这是warn日志...
[2023-10-27 14:25:05.323] [] [main] ERROR: [c.f.LogLog4j2Tests:21] - 这是error日志...
[2023-10-27 14:25:05.329] [] [main] INFO : [c.f.LogLog4j2Tests:22] - 这是info日志...test
[2023-10-27 14:25:05.329] [] [main] INFO : [c.f.LogLog4j2Tests:23] - public class org.apache.logging.slf4j.Log4jLogger
SLF4j Logback binding demo
测试Slf4j binding (桥接到 Logback
)的场景
将原本的Logback
、Log4j2
、Jul
、Jcl
、log4j
的输出,统一到Sfl4j
并最终使用Logback
输出日志
要实现这个效果就必须引入对应日志框架的Slf4j
的Over包,将日志重定向到Slf4j
。但由于Slf4j
并没有一个具体的日志实现,所以还得找一个具体的日志实现,这个demo选择的是Logback
作为最终的日志实现。
引入对应Over包
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
Logback
Over 处理
本Demo是最终是使用Logback
输出,因此不能再把Logback
Over掉了,因此不做Over处理。
Jcl
Over 处理
Jcl
由于Spring 自己做了一个Over的包spring-jcl
,因此如果需要测试验证,还要把这个包给排除掉。
然后引入jcl-over-slf4j
包就可以,当然也可以用spring-jcl
,效果一样。
Log4j
Over 处理
Log4j
除了需要引入log4j-over-slf4j
包外,还要排除掉log4j
本身的依赖包,否则Over是无效的。
<!--引入Log4j-->
<!-- <dependency>-->
<!-- <groupId>log4j</groupId>-->
<!-- <artifactId>log4j</artifactId>-->
<!-- <version>1.2.17</version>-->
<!-- </dependency>-->
Log4j2
Over 处理
log4j2
引入log4j-to-slf4j
这个包。
还需要排除log4j-core
包,当然如果同时存在logback-classic
则不排除也可以正常运行,否则会抛出异常org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
。因为Spring 默认会优先加载Logback的LoggingSystem
的一个实现LogbackLoggingSystem
,当没有的时候才会选择Log4J2LoggingSystem
,但当没有Logback
实现,并且存在log4j-core
时,
将会使用Log4J2LoggingSystem
作为日志的实现,其实也就是一个动态的加载日志实现系统的处理。但log4j-core
不能直接转换到Slf4j
,因此才会抛出上面的异常。
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-core</artifactId>-->
<!-- <version>${log4j2.version}</version>-->
<!-- </dependency>-->
Jul
Over 处理
引入jul-to-slf4j
包。
Jul 在非Spring Boot环境下默认日志配置文件: JVM/lib/logging.properties
Spring Boot中 Jul 的默认配置文件 spring-boot-2.7.9.jar!\org\springframework\boot\logging\java\logging.properties
可以通过 在application.properties
增加下面的配置来指定自定义的配置文件
logging.config=classpath:logging.properties
参考https://www.slf4j.org/legacy.html,https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html 文档,修改默认Handlers,否则Over是不生效的。
简单的方法就是在logging.properties
替换handlers =java.util.logging.ConsoleHandler
配置为handlers = org.slf4j.bridge.SLF4JBridgeHandler
Slf4j
Binding Logback
的处理
引入slf4j
的Logback
实现包logback-classic
<!-- SLF4j binding logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
没有引入对应over依赖包的情况下的输出
日志各自使用各自的输出,JCL
在有Log4j
的时候,使用的就是Log4j
实现。
2023-11-03 17:19:24 DEBUG (com.feiyizhan.LogJclTests:21) - LogJclTests 这是debug日志...
2023-11-03 17:19:24 INFO (com.feiyizhan.LogJclTests:23) - LogJclTests 这是info日志...
2023-11-03 17:19:24 WARN (com.feiyizhan.LogJclTests:24) - LogJclTests 这是warn日志...
2023-11-03 17:19:24 ERROR (com.feiyizhan.LogJclTests:25) - LogJclTests 这是error日志...
2023-11-03 17:19:24 INFO (com.feiyizhan.LogJclTests:26) - LogJclTests public class org.apache.commons.logging.impl.Log4JLogger
十一月 03, 2023 5:19:24 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests 这是info日志...
十一月 03, 2023 5:19:24 下午 com.feiyizhan.LogJulTests printLog
信息: LogJulTests public class java.util.logging.Logger
2023-11-03 17:19:24 DEBUG (com.feiyizhan.LogLog4jTests:21) - LogLog4jTests 这是debug日志...
2023-11-03 17:19:24 INFO (com.feiyizhan.LogLog4jTests:23) - LogLog4jTests 这是info日志...
2023-11-03 17:19:24 WARN (com.feiyizhan.LogLog4jTests:24) - LogLog4jTests 这是warn日志...
2023-11-03 17:19:24 ERROR (com.feiyizhan.LogLog4jTests:25) - LogLog4jTests 这是error日志...
2023-11-03 17:19:24 INFO (com.feiyizhan.LogLog4jTests:26) - LogLog4jTests public class org.apache.log4j.Logger
[2023-11-03 17:19:24.709] [] [main] INFO : [com.feiyizhan.LogBackTests:22] - LogBackTests 这是info日志...
[2023-11-03 17:19:24.712] [] [main] WARN : [com.feiyizhan.LogBackTests:23] - LogBackTests 这是warn日志...
[2023-11-03 17:19:24.712] [] [main] ERROR: [com.feiyizhan.LogBackTests:24] - LogBackTests 这是error日志...
[2023-11-03 17:19:24.712] [] [main] INFO : [com.feiyizhan.LogBackTests:25] - LogBackTests 这是info日志...test
[2023-11-03 17:19:24.714] [] [main] INFO : [com.feiyizhan.LogBackTests:26] - LogBackTests public final class ch.qos.logback.classic.Logger
2023-11-03 17:19:25.185 INFO 11800 --- [ main] c.f.LogLog4j2Tests : LogLog4j2Tests 这是info日志...
2023-11-03 17:19:25.189 WARN 11800 --- [ main] c.f.LogLog4j2Tests : LogLog4j2Tests 这是warn日志...
2023-11-03 17:19:25.189 ERROR 11800 --- [ main] c.f.LogLog4j2Tests : LogLog4j2Tests 这是error日志...
2023-11-03 17:19:25.194 INFO 11800 --- [ main] c.f.LogLog4j2Tests : LogLog4j2Tests 这是info日志...test
2023-11-03 17:19:25.194 INFO 11800 --- [ main] c.f.LogLog4j2Tests : LogLog4j2Tests public class org.apache.logging.log4j.core.Logger
引入对应over依赖包的情况下的输出
全部统一一种日志输出格式了。
[2023-11-03 17:23:25.929] [] [main] INFO : [com.feiyizhan.LogJclTests:23] - LogJclTests 这是info日志...
[2023-11-03 17:23:25.929] [] [main] WARN : [com.feiyizhan.LogJclTests:24] - LogJclTests 这是warn日志...
[2023-11-03 17:23:25.929] [] [main] ERROR: [com.feiyizhan.LogJclTests:25] - LogJclTests 这是error日志...
[2023-11-03 17:23:25.930] [] [main] INFO : [com.feiyizhan.LogJclTests:26] - LogJclTests public class org.apache.commons.logging.impl.SLF4JLocationAwareLog
[2023-11-03 17:23:25.931] [] [main] INFO : [com.feiyizhan.LogJulTests:19] - LogJulTests 这是info日志...
[2023-11-03 17:23:25.931] [] [main] INFO : [com.feiyizhan.LogJulTests:20] - LogJulTests public class java.util.logging.Logger
[2023-11-03 17:23:25.937] [] [main] INFO : [com.feiyizhan.LogLog4jTests:23] - LogLog4jTests 这是info日志...
[2023-11-03 17:23:25.937] [] [main] WARN : [com.feiyizhan.LogLog4jTests:24] - LogLog4jTests 这是warn日志...
[2023-11-03 17:23:25.939] [] [main] ERROR: [com.feiyizhan.LogLog4jTests:25] - LogLog4jTests 这是error日志...
[2023-11-03 17:23:25.939] [] [main] INFO : [com.feiyizhan.LogLog4jTests:26] - LogLog4jTests public class org.apache.log4j.Logger
[2023-11-03 17:23:25.940] [] [main] INFO : [com.feiyizhan.LogBackTests:22] - LogBackTests 这是info日志...
[2023-11-03 17:23:25.943] [] [main] WARN : [com.feiyizhan.LogBackTests:23] - LogBackTests 这是warn日志...
[2023-11-03 17:23:25.943] [] [main] ERROR: [com.feiyizhan.LogBackTests:24] - LogBackTests 这是error日志...
[2023-11-03 17:23:25.946] [] [main] INFO : [com.feiyizhan.LogBackTests:25] - LogBackTests 这是info日志...test
[2023-11-03 17:23:25.949] [] [main] INFO : [com.feiyizhan.LogBackTests:26] - LogBackTests public final class ch.qos.logback.classic.Logger
[2023-11-03 17:23:26.071] [] [main] INFO : [com.feiyizhan.LogLog4j2Tests:20] - LogLog4j2Tests 这是info日志...
[2023-11-03 17:23:26.071] [] [main] WARN : [com.feiyizhan.LogLog4j2Tests:21] - LogLog4j2Tests 这是warn日志...
[2023-11-03 17:23:26.071] [] [main] ERROR: [com.feiyizhan.LogLog4j2Tests:22] - LogLog4j2Tests 这是error日志...
[2023-11-03 17:23:26.083] [] [main] INFO : [com.feiyizhan.LogLog4j2Tests:23] - LogLog4j2Tests 这是info日志...test
[2023-11-03 17:23:26.084] [] [main] INFO : [com.feiyizhan.LogLog4j2Tests:24] - LogLog4j2Tests public class org.apache.logging.slf4j.SLF4JLogger
附录
SLF4J 的常用 Binding 包
<!-- SLF4j binding logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<!--SLF4j simple binding-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--SLF4j binding jul -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- SLF4j binding jcl -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>${slf4j.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- SLF4j binding Log4j (已弃用)-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- SLF4j binding Log4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- SLF4j binding Log4j2-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
SLF4J 的常用 Over 包
<!-- jul over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- jcl over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- lo4j over slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- LOG4J2 over SLF4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>${log4j2.version}</version>
</dependency>
一些相关资源
Log4j2 官网: https://logging.apache.org/log4j/2.x/index.html
SLF4J 官方文档: https://www.slf4j.org/legacy.html
Logback 官网: https://logback.qos.ch/
Log4j2 to Slf4j 官网: https://logging.apache.org/log4j/2.x/log4j-to-slf4j.html