原来一直使用spring mvc,spring框架是3.6.2.配置的是log4j的日志,使用slf4j的log4j结合的方式,最近开发一个新的项目,我搭建了spring boot1.3.6.RELEASE的框架,能使用集成log4j,但是确实有冲突的问题,一直报logback有冲突的信息:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/limm/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
操作:
<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>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
通过依赖树进行了各种排除,才能解决不使用slf4j,使用log4j输出日志,但是接下来进行了spring boot的升级,升级之后才发现springboot 2.x版本不支持log4j了,支持log4j2,既然log4j2是它本来支持的所以准备换成log4j2,配置文件是xml支持原来的log4j.properties,key value的properties文件了。
经过这一番折腾,才发现日志这个体系太繁杂了,所以想梳理一下日志相关的这个体系。
一、日志体系
1. 发展历史
见的Java日志框架有log4j、logback、j.u.l (java.util.logging),常用的日志门面,SLF4J、commons-logging,其中,j.u.l是Java原生库,但是在Java 1.4中才被引用; commons-logging出自Apache,用于桥接j.u.l和log4j;log4j、logback和SLF4J出自同一个作者。
出现的时间顺序:
log4j--->j.u.l----> commons-logging----->SLF4J---->logback
- log4j
在JDK 1.3及以前,Java打日志System.err.println()或者e.printStackTrace(),或者这样根本不算是完善的日志,Debug日志被写到STDOUT流,错误日志被写到STDERR流,这样的日志无法定制,日志粒度小,哪里有压迫哪里就有反抗,哪里有问题,哪里就有有解决问题的办法,所以log4j应运而生 - j.u.l
在log4j之后,可能是受到了log4j的启发,Sun在Java1.4版本中引入了java.util.logging,但是不如log4j完善,需要开发人员编写Appenders(Sun称之为Handlers)。 - commons-logging
第三个出现的是commons-logging,是一个API bridge,可以兼容上面的两个框架,然而commons-logging对Log4j和j.u.l的配置问题兼容的并不好,使用commons-loggings还可能会遇到类加载问题,导致NoClassDefFoundError的错误出现,或许你也经常会遇到这个问题。 - SLF4J
看到上面的这些问题,可能log4j的作者忍不住了(纯属我个人观点),他发起了SLF4j,只要使用SLF4J提供的接口,即可隐藏日志的具体实现,SLF4J提供的核心API是一些接口和一个LoggerFactory的工厂类,大大简便了开发人员的日志配置,方便使用。 - logback
logback和log4j是同一个作者创作,可以认为logback比log4j有更多的优点。
2. Spring 依赖日志包
日志框架出现
先看一下spring boot 2.1.1.RELEASE版本依赖的日志:
从上图可以看出,Spring Boot通过jul-to-slf4j.jar去适配了我们上面提到的JUL日志框架,通过log4j-to-slf4j.jar去适配了log4j日志框架。
Spring5.x相对于Spring4.x去除了原来默认使用的JCL 框架,而是采用SLF4j这个通用的日志门面,所以Spring Boot2.x相对于Spring Boot1.x来说去除了对JCL的适配。
SpringBoot能自动适配所有的日志,其底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要 把这个框架依赖的日志框架排除掉即可,因为Spring Boot会通过自己的jar去替代;
3. logback
logback
日志级别:
logbac日志级别从低到高分别为TRACE, DEBUG, INFO, WARN, ERROR
配置文件:
logback.xml也可以命名为