背景

一个爬虫项目遇到了反爬,需要验证下代理 IP 能否解决反爬问题,所以在项目中引入了 spring-boot-starter-data-redis 用 RedisTemplate 来存储爬来的代理 IP。项目的日志框架是 slf4j-api,运行正常。

但是引入这个新依赖配置后,启动报错:

Caused by: java.lang.IllegalArgumentException: 
LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. 
复制代码

日志框架变成了 logback 了,本文来梳理一下 SpringBoot 引入 log4j 日志框架的流程,出现该问题的原因及解决办法。

log4j 配置

项目使用 log4j ,那么需要引入 slf4j-api 并且将 SpringBoot 启动模块依赖的日志包剔除,pom.xml 配置文件如下:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>${springboot.version}</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
      </exclusions>
    </dependency>复制代码

引入目标日志包:

<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.7</version>
    </dependency>复制代码

spring-boot-starter-data-redis

这个依赖包引入之后,我们可以看到它引入的其他包结构为:SpringBoot 引入依赖包中的日志覆盖现有日志问题分析_SpringBoot 找到症结:它依赖了 logback 的日志框架,从而覆盖了项目原有的日志配置。

解决办法

新引入的依赖包包含了默认日志框架,也需要排除:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <exclusions>
        <!--排除默认的日志依赖包,否则启动应用报错-->
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
      </exclusions>
    </dependency>复制代码

启示录

说来惭愧,出现问题第一反应竟然是百度异常信息,看了一些搜索结果都不是问题原因,于是放了一夜。今天觉得从日志配置的源头来分析问题,找到日志配置的关键是排除starter 中的日志包。

去掉新依赖包,工程正常启动;再加上依赖,展开相关依赖结构果然发现了默认日志包,添加排除配置后,问题解决。