外部Tomcat部署Spring Boot WAR启动失败:spring-ws-core冲突
问题:Spring Boot WAR部署到外部Tomcat时排除指定共享依赖
将Spring Boot Web应用打包为WAR部署到运行有多个Spring/非Spring Boot应用的外部Tomcat服务器,服务器通过catalina.properties的common.loader配置加载共享位置的依赖包。启动该Spring Boot应用时出现如下CGLIB相关异常,排查确认是共享的spring-ws-core.jar导致(本应用无需此依赖),但其他应用依赖该Jar无法删除,需实现让特定应用不加载这个共享Jar。
错误日志
java.lang.IllegalStateException: Error starting child at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:686) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:658) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:661) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1023) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1910) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112) at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:824) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:474) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1617) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:318) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:114) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402) at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:345) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:893) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:794) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:248) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:433) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:921) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) at org.apache.catalina.startup.Catalina.start(Catalina.java:772) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:347) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:478) Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/myservice]] at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:419) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:186) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:683) ... 37 more Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.NoSuchMethodException-->org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$47de5974.CGLIB$SET_THREAD_CALLBACKS([Lorg.springframework.cglib.proxy.Callback;) at org.springframework.cglib.proxy.Enhancer$EnhancerFactoryData.<init>(Enhancer.java:513) at org.springframework.cglib.proxy.Enhancer.wrapCachedClass(Enhancer.java:806) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:111) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572) at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:419) at org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(ConfigurationClassEnhancer.java:137) at org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(ConfigurationClassEnhancer.java:109) at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:447) at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:268) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:147) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:748) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:175) at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:155) at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:97) at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4904) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ... 38 more Caused by: java.lang.NoSuchMethodException: org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$47de5974.CGLIB$SET_THREAD_CALLBACKS([Lorg.springframework.cglib.proxy.Callback;) at java.lang.Class.getDeclaredMethod(Class.java:2130) at org.springframework.cglib.proxy.Enhancer.getCallbacksSetter(Enhancer.java:912) at org.springframework.cglib.proxy.Enhancer.access$000(Enhancer.java:93) at org.springframework.cglib.proxy.Enhancer$EnhancerFactoryData.<init>(Enhancer.java:502) ... 67 more
解决方案
1. 配置Tomcat上下文排除指定Jar
为该Spring Boot应用创建单独的上下文配置文件:
- 方式一:在应用WAR包的
META-INF目录下创建context.xml - 方式二:在Tomcat服务器的
conf/Catalina/localhost/目录下创建[应用名].xml(比如应用路径是/myservice,则创建myservice.xml)
在配置文件中添加Jar扫描过滤规则,跳过spring-ws-core相关Jar:
<Context> <JarScanner> <JarScanFilter defaultPluggabilityScan="true" tldSkip="spring-ws-core*.jar" pluggabilitySkip="spring-ws-core*.jar"/> </JarScanner> </Context>
Tomcat加载该应用时会跳过指定Jar,不会加载其中的类和配置。
2. 显式排除Spring Boot自动配置类
直接在Spring Boot启动类上排除Web Services相关的自动配置类,避免Spring初始化不必要的组件:
@SpringBootApplication(exclude = {WebServicesAutoConfiguration.class}) public class YourApplication extends SpringBootServletInitializer { // 启动类逻辑 }
若使用较旧版本的Spring Boot,可根据实际依赖调整排除的配置类(如WsConfigurationSupport)。
3. 调整Tomcat类加载器隔离策略
修改Tomcat的类加载配置,将共享依赖与目标应用隔离:
- 修改
catalina.properties,把spring-ws-core.jar从common.loader移到shared.loader:shared.loader=${catalina.base}/shared/lib/spring-ws-core*.jar,... - 在应用的
context.xml中指定使用独立的Webapp类加载器,不加载shared目录的依赖:<Context loader="webapp"> <!-- 其他上下文配置 --> </Context>
该应用将仅加载自身WEB-INF/lib下的依赖,完全隔离共享的spring-ws-core.jar。
内容的提问来源于stack exchange,提问作者DpkTheJavaCoder
相关产品推荐
相关产品推荐

