这篇文章继续介绍Spring Boot 1.5.22升级至2.x在运行阶段一部分可能会出先的问题。
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/liumiao/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.13.3/log4j-slf4j-impl-2.13.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/liumiao/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.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 [org.apache.logging.slf4j.Log4jLoggerFactory]
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.XXXXXXXXX.main(YYYYYYYY.java:33)
Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
at org.apache.logging.slf4j.Log4jLoggerFactory.validateContext(Log4jLoggerFactory.java:49)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:39)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:30)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:54)
at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:30)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:363)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:273)
at org.springframework.boot.SpringApplication.(SpringApplication.java:196)
... 1 more
写的已经很清楚了,log4j-slf4j-impl cannot be present with log4j-to-slf4j,Spring自带的项目使用的冲突了。
将Spring自带的冲突了,可在depencency中进行排除,在pom中如下设定即可
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
exclusions>
dependency>
[main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.NoClassDefFoundError: org/joda/time/YearMonth
at org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar.registerFormatters(JodaTimeFormatterRegistrar.java:203) ~[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.format.support.DefaultFormattingConversionService.addDefaultFormatters(DefaultFormattingConversionService.java:127) ~[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
at org.springframework.boot.convert.ApplicationConversionService.configure(ApplicationConversionService.java:98) ~[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.convert.ApplicationConversionService.(ApplicationConversionService.java:61) ~[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.convert.ApplicationConversionService.(ApplicationConversionService.java:54) ~[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.convert.ApplicationConversionService.getSharedInstance(ApplicationConversionService.java:80) ~[spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.configureEnvironment(SpringApplication.java:478) [spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:343) [spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.3.RELEASE.jar!/:2.3.3.RELEASE]
at YYYY.XXXX.main(XXXX.java:33) [classes!/:1.0-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_191]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_191]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_191]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_191]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [bootstrap-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:109) [bootstrap-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [bootstrap-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) [bootstrap-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
Caused by: java.lang.ClassNotFoundException: org.joda.time.YearMonth
at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[?:1.8.0_191]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_191]
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) ~[bootstrap-1.0-SNAPSHOT.jar:1.0-SNAPSHOT]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_191]
... 20 more
提示的很清楚了,缺少joda-time的依赖
添加上去即可,目前的版本为2.10.6
[main] WARN org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:A.jar!/BOOT-INF/lib/B.jar!C.class]; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [D] for bean with name 'E' defined in URL [jar:file:XXXX]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/web/support/SpringBootServletInitializer
[main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:XXXXXX.class]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/web/support/SpringBootServletInitializer
...
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [XXXX]: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/web/support/SpringBootServletInitializer
...
原因往往多因为新旧版本的jar文件在使用中的冲突,本文碰到的情况为使用的是升级之前的依赖。
最简单的方式可以删除所有的依赖,干净地全编译一遍。也可以具体根据Caused by的部分都进行install,一般可以解决
WARN org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'XXX' defined in class path resource [XXXX] for bean 'XXX': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=devopsApplication; factoryMethodName=getGitHookService; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [YYYY]] bound.
ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'XXX', defined in class path resource [AAAA], could not be registered. A bean with that name has already been defined in class path resource [BBBB] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
Spring Boot检测到bean的重复,认为需要修改或者显示将允许bean定义覆盖的选项设定为true
除了修改代码,可以按照提示的Action部分所说的那样,将spring.main.allow-bean-definition-overriding设定为true即可。
[main] ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter -
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.data.redis.repository.configuration.RedisRepositoryConfigurationExtension.registerBeansForRoot(RedisRepositoryConfigurationExtension.java:87)
The following method did not exist:
org.springframework.data.repository.config.RepositoryConfigurationSource.getAttribute(Ljava/lang/String;)Ljava/lang/String;
The method's class, org.springframework.data.repository.config.RepositoryConfigurationSource, is available from the following locations:
jar:file:/Users/liumiao/.m2/repository/XXXXX!/BOOT-INF/lib/spring-data-commons-2.3.3.RELEASE.jar!/org/springframework/data/repository/config/RepositoryConfigurationSource.class
The class hierarchy was loaded from the following locations:
org.springframework.data.repository.config.RepositoryConfigurationSource: jar:file:/Users/liumiao/.m2/repository/XXXXXX/BOOT-INF/lib/spring-data-commons-2.3.3.RELEASE.jar!/
Redis相关版本冲突
这里统一升级为当前最新兼容的版本
org.springframework.data
spring-data-redis
2.3.3.RELEASE
org.springframework.session
spring-session-data-redis
2.3.0.RELEASE
redis.clients
jedis
3.3.0
修改之后全编译出现如下错误
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project bootstrap: Compilation failure: Compilation failure:
[ERROR] YYYYY.java:[11,44] cannot find symbol
[ERROR] symbol: class CookieHttpSessionStrategy
[ERROR] location: package org.springframework.session.web.http
[ERROR] YYYY.java:[12,44] cannot find symbol
[ERROR] symbol: class HttpSessionStrategy
[ERROR] location: package org.springframework.session.web.http
[ERROR] YYYY.java:[87,12] cannot find symbol
[ERROR] symbol: class HttpSessionStrategy
[ERROR] location: class ZZZZ
CookieHttpSessionStrategy和HttpSessionStrategy在Spirng Boot 2早期的版本中还存在,2.0的正式版本中被移除
修改前(定义部分)
import org.springframework.session.web.http.CookieHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
修改前(使用部分)
public HttpSessionStrategy httpSessionStrategy(){
return new CookieHttpSessionStrategy();
}
修改后(定义部分)
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
修改前(使用部分)
public CookieSerializer httpSessionStrategy(){
return new DefaultCookieSerializer();
}