梳理Java当前主流的日志体系

文章目录

梳理Java当前主流的日志体系

当前主流的日志框架有
JUL: Java.util.logging ,JDK 自带的日志实现
JCL: 全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging", 一套日志门面 ,只支持JULLog4j
SLF4J: 全称为"Simple Logging Facade For Java",一套日志门面,支持几乎当前所有主流的日志框架。
Log4j: Log for Java
Log4j2 : Log4j 的升级 ,Log4j2Log4j是一个作者,只不过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,这个是包是处理JCLSLF4J的,因此如果要修改为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 默认引入了JCLSLF4j 两个门面,因此如果只测试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 默认引入了JCLSLF4j 两个门面,因此如果只测试Log4j2 就需要排除spring-jclslf4j-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门面和logbackslf4j门面的实现,因此引入这个一个包就可以了。

注: JDK8 只能使用1.3及以下版本,1.4以上版要求JDK11,详情参考:https://logback.qos.ch/news.html

Spring 默认引入了JCLSLF4j 两个门面,因此如果只测试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 默认引入了JCLSLF4j 两个门面,因此如果只测试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 默认引入了JCLSLF4j 两个门面,因此如果只测试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 )的场景
将原本的LogbackLog4j2JulJcllog4j的输出,统一到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-slf4jslf4j-jdk14 不能同时引入,因为一个是将Jul重定向到slf4j,另一个是将slf4j的日志输出使用Jul来输出。
jslf4j-jdk14 不能同时引入,因为一个是将Jul重定向到slf4j,另一个是将slf4j的日志输出使用Jul`来输出。

SLF4J Binding Jul的处理

引入slf4jJul实现包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 )的场景
将原本的LogbackLog4j2JulJcllog4j的输出,统一到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-slf4jslf4j-jdk14 不能同时引入,因为一个是将Jul重定向到slf4j,另一个是将slf4j的日志输出使用Jul来输出。

SLF4J Binding Slf4j-Simple 的处理

引入slf4jSimple实现包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 )的场景
将原本的LogbackLog4j2JulJcllog4j的输出,统一到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作为输出,因此排除JclOver

<!-- jcl over slf4j -->
<!--<dependency>-->
<!--  <groupId>org.slf4j</groupId>-->
<!--  <artifactId>jcl-over-slf4j</artifactId>-->
<!--  <version>${slf4j.version}</version>-->
<!--</dependency>-->
Log4j Over 处理

本demo 最终使用Log4jJcl的实现,不能再对Log4jOver,因此需要排除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-slf4jslf4j-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 )的场景
将原本的LogbackLog4j2JulJcllog4j的输出,统一到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 的处理

引入slf4jLog4j2实现包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 )的场景
将原本的LogbackLog4j2JulJcllog4j的输出,统一到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 的处理

引入slf4jLogback实现包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

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值