Springboot中默认的日志组件为logback组件,如果要修改默认的日志组件,修改为log4j2性能更好的日志组件,在一般的文章中,都会给出如下的配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 去掉默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入log4j2依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
这种配置方法在某些条件下是没有问题的,但是在有些情况下,尤其是Springboot项目的情况复杂,如果只是这么配置有时候不会生效。
这是为什么呢?
因为提出的解决方案只是在经典的环境中,而且这种经典环境没有人去描述,或者大部分人也是人云亦云,不知道还有一个解决方案可以生效的一个前提条件或者环境。
我按照博客进行了配置,出现的不能生效的问题,尝试通过jar的依赖关系来查看为什么配置没有生效。
第一步,打开项目的pom.xml文件,右键弹出菜单,选择“Diagrams”-“Show Dependencies…”;
选择“Diagrams”-“Show Dependencies…”
出现jar的依赖关系图,如下图所示,logback-classic和log4j-api的依赖路径一样长,但是logback是声明在前,所以项目的日志组件为logback。
POM依赖关系图
那么如何让log4j2生效了,其实maven的规则就为我们提供了解决方案,一是缩短log4j2的依赖路径,一是排除logback依赖。
根据上图logback的依赖关系,往上寻找,是spring-boot-starter-jdbc引入的,而且spring-boot-starter-jdbc在spring-boot-starter-web声明之前,因此有两种方案解决。
一是,把spring-boot-starter-web和spring-boot-starter-log4j2放到spring-boot-starter-jdbc前面。
把spring-boot-starter-web和spring-boot-starter-log4j2放到spring-boot-starter-jdbc前面
二是,在spring-boot-starter-jdbc中添加排除logback。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<!-- 去掉默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
附录:Maven依赖优先级规则
1、依赖最短路径优先的原则
假设一个Springboot项目的jar包X具有如下的依赖关系,其中A-B-C-X(1.0) , A-D-X(1.1)。由于X(1.1)路径最短,所以项目使用的是X(1.1)。
2、POM文件中声明顺序优先
假设A-B-X(1.0) ,A-D-X(1.1)的依赖路径长度一样,应该怎么处理呢?此种情况下,Maven会根据Pom文件声明的顺序加载,如果先声明了B,后声明了D,那就最后的依赖就会是X(1.0)。
3、覆盖优先原则
如果是多Module的Springboot项目,那么孩子Pom内声明的依赖,优先于父Pom中的依赖。
总结
具体问题的解决方案,必须要考虑整体的环境,离开整体环境谈解决方案,必然会出现各种所谓奇怪的情况。所谓奇怪只是不了解事情的全局、规则和原理,只是按部就班的操作。
因此解决问题,要从系统思维的角度去解决,弄懂问题的底层逻辑,弄清楚事情的规律和原理,这样解决一个问题就解决了一类问题,否则总是陷入无数个局部中去不能自拔。