Spring Boot打可部署WAR包部署Tomcat9报NoClassDefFoundError: AdviceMode
问题根因分析
首先要澄清一个容易误导的现象:移除主类对SpringBootServletInitializer的继承后异常消失,本质是因为该类是外部Tomcat部署时触发Spring上下文初始化的入口——去掉继承后,Tomcat启动时根本不会加载Spring容器,自然不会走到需要加载AdviceMode类的流程,并不是问题被解决了。
真正触发异常的核心原因是pom.xml中的冗余手动配置:
- Spring Boot 2.4.4 的依赖管理体系本身已经完成了所有Spring Framework组件的版本对齐,其管理的Spring版本正好是5.3.5,完全不需要手动单独声明
spring-core、spring-context的依赖。 - 手动硬编码这两个依赖的版本后,会打乱Maven的依赖调解逻辑,导致
spring-boot-maven-plugin在执行WAR重打包时出现路径识别错误:本该放入WEB-INF/lib目录的Spring核心jar,会被错误识别为provided范围,放到外部Tomcat默认不会加载的WEB-INF/lib-provided目录下。 - 这也解释了为什么可执行JAR模式运行完全正常:可执行JAR的类加载流程由Spring Boot自身控制,会主动加载
BOOT-INF/lib下的所有依赖,不受外部Tomcat的类加载路径规则限制。
可落地的解决方案
- 删掉pom.xml里手动声明的
spring-core、spring-context两段依赖配置,完全交给spring-boot-starter-parent统一管理所有Spring相关组件的版本,避免版本和路径冲突。 - 保留已配置正确的
spring-boot-starter-tomcat的provided范围声明,确保内嵌Tomcat不会被打包进WAR。 - 执行
mvn clean清理历史构建产物,重新打包WAR,验证包结构:- 确认
spring-context、spring-core、spring-beans等Spring核心jar包位于WEB-INF/lib目录下,而不是WEB-INF/lib-provided目录。
- 确认
- 部署前检查Tomcat的共享lib目录,确保没有额外放置的低版本Spring jar,避免类加载顺序优先加载到不兼容的类版本。
- 如果重新打包后仍有类加载问题,可以执行
mvn dependency:tree排查依赖树,确认所有spring-*组件版本完全一致,没有多版本混用的情况。
内容的提问来源于stack exchange,提问作者Soynuts123
相关产品推荐
相关产品推荐

