记录日志中logback和log4j2不能共存的问题
本文章记录设置两个日志时候,控制台直接报错
标黄处就是错误原因:1. SLF4J(W):类路径包含多个SLF4J提供程序。
SLF4J(W):找到提供程序[org.apache.logging.slf4j. net]。
SLF4J(W):找到提供程序[ch.qos.log .classic.spi. SLF4JServiceProvider@50d0686]。
SLF4J(I):实际提供程序的类型为[org.apache.logging.slf4j]。SLF4JServiceProvider@50d0686]线程“main”异常java.lang.ExceptionInInitializerError:
从而引起的记录异常 : 2. log4j-slf4j2-impl不能与log4j-to-slf4j一起出现
下面分析原因:
-
两者都是日志的实现方式,也是当下最流行的,但是 logback是官方提供的,而 slf4j是开源的,也就是说两者作者不是一个人
-
但是这也不是二者起冲突的原因,主要原因是因为以下两点(如图所示)
-
1. 重复引入 slf4j-api,这可能会导致类路径中存在 多个 SLF4J API 的版本
-
2. 日志实现的多重性
-
项目中同时引入了
log4j-to-slf4j
以及spring-boot-starter-logging两个依赖,导致日志的实现冲突,在
spring-boot-starter-logging 中,期望的是使用Logback,使用的是jul-to-slf4j
桥接器;而log4j-to-slf4j
桥接器试图将 Log4j 的日志转换为 SLF4J 的日志。 注意:spring-boot-starter-web中已经包含了spring-boot-starter-logging依赖;
-
-
3. log4j-slf4j2-impl
和log4j-to-slf4j
之间的不兼容性主要源于它们各自的设计使用不同。-
区别:它们处理的日志框架不同(Log4j 1 与 Log4j 2)
log4j-slf4j2-impl
:这是 Log4j 2 的实现,它将 SLF4J 日志调用传递给 Log4j 2。这意味着当您使用 SLF4J API 记录日志时,日志消息实际上会被 Log4j 2 处理。这种实现是专门为支持新的 Log4j 2 框架而设计的。log4j-to-slf4j
:这是一个桥接器,用于将 Log4j 1 的日志事件转发到 SLF4J。这意味着它使得 Log4j 1 的用户能够无缝地使用 SLF4J,而不需要修改代码来适应 SLF4J。
-
引发的问题:
- Log4j 2 期望接收 SLF4J 的调用并基于此生成日志。Log4j 1(通过
log4j-to-slf4j
)则尝试将 Log4j 事件转发到 SLF4J。 - SLF4J 的调用可能被 指向 Log4j 2 实现,但依赖于
log4j-to-slf4j
的 Log4j 1 的事件则可能无法被正确处理。这样可能导致日志丢失、重复记录或混乱的日志输出。
- Log4j 2 期望接收 SLF4J 的调用并基于此生成日志。Log4j 1(通过
-
-
-
解决方法:
-
根据项目需要选择其中一个,并移除不必要的日志实现依赖。
-
一般的项目默认使用的都是 Logback日志的实现,导致冲突都是引入Log4j2 日志实现而引起的。
-
所以下面方法是针对 要使用Log4j2 作为日志实现方式的修改
-
排除Logback日志的实现方式
<!--web前端互动的依赖--> <!-- -starter-web 依赖中自动添加了 starter-logging 也就是logback 日志实现方式 的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--由于 引入了log4j2 日志实现方式 的依赖,两个日志实现方式会同时引入两种桥接器,导致程序报错。 --> <!--排除starter-logging 也就是logback 日志实现方式 的依赖--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
-
-
-
下面是我遇见的其他问题
在完成上面操作后,还是不能排除 spring-boot-starter-logging 依赖项,通过 mvn dependency:tree 查看了依赖树,发现在: spring-boot-starter 依赖中也包含这这个依赖项,检查pom.xml文件发现没有这个依赖项,最后在父工程的pom.xml中发现这个依赖。