Java Springboot 使用druid连接池抛java.lang.ClassNotFoundException: org.apache.log4j.Logger

    xiaoxiao2022-07-04  220

     

    废话少说直接上错误日志:


    Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/Logger at com.alibaba.druid.filter.logging.Log4jFilter.<init>(Log4jFilter.java:26) ~[druid-1.1.9.jar:1.1.9] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_91] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_91] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_91] at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_91] at java.lang.Class.newInstance(Class.java:442) ~[?:1.8.0_91] at com.alibaba.druid.filter.FilterManager.loadFilter(FilterManager.java:114) ~[druid-1.1.9.jar:1.1.9] at com.alibaba.druid.pool.DruidAbstractDataSource.addFilters(DruidAbstractDataSource.java:1286) ~[druid-1.1.9.jar:1.1.9] at com.alibaba.druid.pool.DruidAbstractDataSource.setFilters(DruidAbstractDataSource.java:1275) ~[druid-1.1.9.jar:1.1.9] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.duridDataSource(DynamicDataSourceRegister.java:220) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.buildDataSource(DynamicDataSourceRegister.java:123) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.initDefaultDataSource(DynamicDataSourceRegister.java:156) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.setEnvironment(DynamicDataSourceRegister.java:136) ~[classes/:?] at org.springframework.context.annotation.ParserStrategyUtils.invokeAwareMethods(ParserStrategyUtils.java:59) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:626) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE] ... 22 more Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:1.8.0_91] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_91] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[?:1.8.0_91] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_91] at com.alibaba.druid.filter.logging.Log4jFilter.<init>(Log4jFilter.java:26) ~[druid-1.1.9.jar:1.1.9] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_91] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_91] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_91] at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_91] at java.lang.Class.newInstance(Class.java:442) ~[?:1.8.0_91] at com.alibaba.druid.filter.FilterManager.loadFilter(FilterManager.java:114) ~[druid-1.1.9.jar:1.1.9] at com.alibaba.druid.pool.DruidAbstractDataSource.addFilters(DruidAbstractDataSource.java:1286) ~[druid-1.1.9.jar:1.1.9] at com.alibaba.druid.pool.DruidAbstractDataSource.setFilters(DruidAbstractDataSource.java:1275) ~[druid-1.1.9.jar:1.1.9] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.duridDataSource(DynamicDataSourceRegister.java:220) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.buildDataSource(DynamicDataSourceRegister.java:123) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.initDefaultDataSource(DynamicDataSourceRegister.java:156) ~[classes/:?] at com.autohome.wz.business.mallOperation.webboot.datasource.DynamicDataSourceRegister.setEnvironment(DynamicDataSourceRegister.java:136) ~[classes/:?] at org.springframework.context.annotation.ParserStrategyUtils.invokeAwareMethods(ParserStrategyUtils.java:59) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE] at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:626) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE] ... 22 more Disconnected from the target VM, address: '127.0.0.1:59371', transport: 'socket'

    解决方案1:亲测不太好使  可以添加jar解决(实际并未解决)

    <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>

    即使能解决这样也有弊端:弊端如下

    但是这样导致的问题是SpringBoot和Druid分别用自己的日志框架,SpringBoot用的是slf4j和logback。druid使用的日志框架是log4j,个人比较推荐的做法:引入log4j-over-slf4j包,作用是通过中间包来替换log4j日志框架,所有日志最终都统一到slf4j,并由logback实现。

    解决方案2:

    log4j-over-slf4j: To use log4j-over-slf4j in your own application, the first step is to locate and then to replace log4j.jar with log4j-over-slf4j.jar. Note that you still need an SLF4J binding and its dependencies for log4j-over-slf4j to work properly.

    In most situations, replacing a jar file is all it takes in order to migrate from log4j to SLF4J.

    Note that as a result of this migration, log4j configuration files will no longer be picked up. If you need to migrate your log4j.properties file to logback, the log4j translator (用这个可以将log4j的配置文件转换成logback的配置文件)might be of help. For configuring logback, please refer to its manual.


    SLF4J作为一个服务很多日志框架的门店或者抽象,一些相关插件使用了设计模式中的门面模式以及代理模式,我们可以SLF4J这个框架很容易就切换具体的日志框架,比如logback、log4j等,还能将使用log4j日志框架输出的日志路由到SLF4J上(通过org.slf4j:log4j-over-slf4j:jar这个jar包实现)。 特别需要指出的是SLF4J采用的是动态绑定具体日志框架的方式,根据classpath目录下放置的绑定jar包来实现绑定,常见绑定jar包如下:

    具体用法:使用log4j-over-slf4j取代log4j,这样log4j接口输出的日志就会通过log4j-over-slf4j路由到SLF4J上,这样即使系统(包含使用的第三方jar库,比如dubbo)都可以将日志最终路由到SLF4J上,进而集中输出。

    工作原理 本文就以log4j-over-slf4j这个jar库为例来说明这其中的原理:

    这个里面使用的是迷惑战术,按照log4j库的目录排布放置几个相关类(比如Logger等),这样系统中使用log4j的代码编译就不会出错,但是这些代理logger内部实现时却将日志悄悄代理到了SLF4J相关接口,相关部分代码如下: 

    public void debug(Object message){     differentiatedLog(null, CATEGORY_FQCN, 10, message, null); } public void info(Object message, Throwable t){     differentiatedLog(null, CATEGORY_FQCN, 20, message, t); }

    下面将揭开庐山真面目:

     protected Logger slf4jLogger;  --org.apache.log4j.Category类属性,该属性就是org.slf4j.Logger类型了,到此相信大家已经知道了绑定类的工作原理。

    void differentiatedLog(Marker marker, String fqcn, int level, Object message, Throwable t){     String m = convertToString(message);     if (this.locationAwareLogger != null) {       this.locationAwareLogger.log(marker, fqcn, level, m, null, t);     } else {       switch (level){       case 0:          this.slf4jLogger.trace(marker, m);         break;       case 10:          this.slf4jLogger.debug(marker, m);         break;       case 20:          this.slf4jLogger.info(marker, m);         break;       case 30:          this.slf4jLogger.warn(marker, m);         break;       case 40:          this.slf4jLogger.error(marker, m);       }    } }

     

    最新回复(0)