logback集成spring
最近上马的一个项目准备采用开源项目二次开发,记过发现好多坑,这里主要就说说日志打印的坑。
项目里看到了logback.xml配置文件,但是无论怎么配置都没有用。最后回过头来检查配置发现居然连logback该配置的监听都没有在web.xml配置。项目是maven的,检查发现logback集成的基本jar也没有完全引入。
一、logback集成spring的基本jar引入
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
以上就是pom关于日志引入的jar,大家觉得是不是缺少点什么?没错,这样根本就不会有用,因为这根本就没有与spring集成起来。
这里埋的坑就是没有引入spring的支持jar。实际上logback集成spring是需要一个logback-ext-spring的jar支持的。目前spring貌似还不能缺少这个jar直接用logback。
首先是要引入spring对logback支持的jar
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>${logback-extensions.version}</version>
</dependency>
其次在web.xml需要配置监听
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>classpath:logback.xml</param-value>
</context-param>
<listener>
<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>
然后就是logback.xml的配置文件了,
logback与log4j一样,也需要在classpath中编写配置文件。但logback配置文件似乎比log4j复杂一些:log4j不仅支持xml格式的配置文件,还支持properties格式的,而logback只支持xml格式的。好在官方提供了一个在线工具,可以将log4j的properties文件直接转换成logback的xml文件,地址如下:
logback的详细用法及其xml文件的相关语法,可参见它的用户向导,地址如下:
到此才是真正配置完成了,但是实际上你还是会遇到一些坑。现在我们来说下可能会遇到的坑:
1、LogbackConfigListener监听不能实例化
这里其实也说明了原因,看SLF4J开头的2行日志,其实这个不是根本原因,上面在引入logback支持的3个基本jar时有个坑,这也是开源故意还是有意就不知道了(jcl-over-slf4j不算必须的jar),注意看logback-classic引入,里面的scope节点设置的是test,这个的意思是什么呢?下面补充下maven的scope标签的知识:
<scope>test</scope>
<!--依赖范围。在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。
- compile :默认范围,用于编译
- provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath
- runtime: 在执行时需要使用
- test: 用于test任务时使用
- system: 需要外在提供相应的元素。通过systemPath来取得
- systemPath: 仅用于范围为system。提供相应的路径
- optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用-->
设置的是test,说明不会把jar加到项目的lib下,我自己也检查了maven install出来的项目war包,确实里面是没有这个包的。
2、SLF4J: Class path contains multiple SLF4J bindings.
看到没,这时候虽然是开始打印日志了,达到了目的,但是还有警告提示,这里实际上是告诉你,2个jar里都有这个StaticLoggerBinder,这就是个赌jar的加载顺序和版本的问题,可能换个版本,方法就不一定兼容了,可能那次不是调用的logback-classic-1.2.3.jar里的方法就会包classNotFound了或其他错了。
这个问题很蛋疼,说实话slf4j-log4j12都不知道怎么来的,在pom里没有引入这个,开源项目因为有大概10个jar是自己封装的,怀疑是他们封装的jar里包含了这个,准备用exclusions去掉他们的jar对这个jar的依赖的,但是jar太多,实在懒得一个个反编译jar看。这个地方很诡异,纠结了好久,最后还是收scope标签的启发,既然这样,我为什么不能自己主动引入这个jar,然后增加这个标签,设值为test,这样不就不会加到项目的lib里面了吗???试试
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
<scope>test</scope>
</dependency>
结果:
但是其实并不是完美解决,这样会导致junit单元测试没有办法使用。最后还是把本地的每个jar反编译看了,最后在jug-2.0.jar里发现了log4logger.class,于是在jug的引入增加
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
即:
maven install一遍,看看junit的类是否可以运行成功,即:
完美解决。需要学些junit集成的可以查看我的其他文章,谢谢。
补充说明,如果logback.xml在classpath下面,是不需要在web.xml里面配置任何信息的,包括监听、配置文件路径的配置。
下面补充下相关内容:
1、maven标签详解
2、logback.xml配置详解
这是一系列的。
3、之前还有一个jar:jcl-over-slf4j,不知道这大家搞清楚没有是干啥的。这里解释下:
第一个logback-classic包含了logback本身所需的slf4j-api.jar、logback-core.jar及logback-classsic.jar
第二个logback-ext-spring是由官方提供的对Spring的支持,它的作用就相当于log4j中的Log4jConfigListener;这个listener,网上大多都是用的自己实现的,原因在于这个插件似乎并没有出现在官方文档的显要位置导致大多数人并不知道它的存在
第三个jcl-over-slf4j是用来把Spring源代码中大量使用到的commons-logging替换成slf4j,只有在添加了这个依赖之后才能看到Spring框架本身打印的日志,否则只能看到开发者自己打印的日志
4、为什么用logback作为日志处理组件?
logback替代log4j作为Spring MVC项目的日志处理组件。这两者虽然作者相同,但log4j早已被托管给Apache基金会维护,并且自从2012年5月之后就没有更新了。而logback从出生开始就是其作者奔着取代log4j的目的开发的,因此一方面logback继承了log4j大量的用法,使得学习和迁移的成本不高,另一方面logback在性能上要明显优于log4j,尤其是在大量并发的环境下,并且新增了一些log4j所没有的功能(如将日志文件压缩成zip包等)