Bootstrap

记录日志中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 的事件则可能无法被正确处理这样可能导致日志丢失、重复记录或混乱的日志输出。

    • 解决方法:

      • 根据项目需要选择其中一个,并移除不必要的日志实现依赖。

        • 一般的项目默认使用的都是 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中发现这个依赖。

;