Maven多模块项目部署Tomcat7时部分类报ClassNotFoundException
这种部分类能正常加载、部分报ClassNotFoundException的情况,在Tomcat + Maven多模块的场景里真的挺常见的,我来梳理几个核心的排查和解决方向:
1. 先揪出依赖范围(scope)的问题
这是最容易踩的坑!如果底层项目里某些类依赖的库被设成了provided或者test,上层war打包时Maven会自动跳过这些依赖,而Tomcat本身又没提供这些类,自然就找不到了。比如底层API用到了某个第三方工具库,结果scope写成provided,上层项目又没显式引入,部署后肯定报错。
- 排查动作:打开底层项目的
pom.xml,逐个检查<dependency>标签的scope属性,确保必要的依赖都是compile(默认值,不用显式写);再用mvn dependency:tree查看上层项目的依赖树,确认底层项目的所有依赖都被正确传递过来,没有被意外排除。 - 解决方法:把错误设置的
scope改回compile,如果是Tomcat已经提供的依赖(比如Servlet API、JSP API),那底层项目可以设为provided,但上层项目也要保持一致,避免重复打包。
2. 检查Tomcat类加载器的优先级冲突
Tomcat的类加载器是分层的:Bootstrap → System → Common → Webapp。如果Webapp里的某个类和Tomcat自带的类(比如Common目录下的jar)重名或者版本冲突,就可能出现部分类加载异常的情况。比如底层项目用的Commons Logging版本和Tomcat自带的不一样,就可能导致加载混乱。
- 排查动作:启动Tomcat时加上
-verbose:class参数,这样会打印每个类的加载路径,你就能看到报错的类是从哪里加载的——是Webapp的lib,还是Tomcat的自带lib? - 解决方法:
- 如果是和Tomcat自带库冲突,把冲突的依赖在pom里设为
provided,让Tomcat用自带的版本; - 如果必须用自己的版本,可以修改Tomcat的
conf/catalina.properties,在tomcat.util.scan.DefaultJarScanner.jarsToSkip里添加冲突的jar名,让Tomcat跳过加载它。
- 如果是和Tomcat自带库冲突,把冲突的依赖在pom里设为
3. 确认Maven打包时的依赖遗漏或重复
有时候Maven的依赖传递会“掉链子”——比如底层项目的某个模块没被正确引入到上层,或者有依赖排除规则把必要的类给排除了;另外,如果上层war里存在多个版本的同一个jar,也会导致类加载逻辑混乱。
- 排查动作:
- 用
mvn dependency:tree > dependency.log导出上层项目的依赖树,搜索报错类所在的jar,看看是不是被排除了; - 解压上层项目的war包,查看
WEB-INF/lib目录,确认底层项目的jar存在,且没有重复的jar(比如同时有xxx-1.0.jar和xxx-2.0.jar)。
- 用
- 解决方法:
- 如果依赖被排除了,在上层项目的pom里显式引入该依赖,或者调整
<exclusions>规则; - 如果有重复jar,用
<exclusions>把多余的版本排除掉,确保只保留需要的那个。
- 如果依赖被排除了,在上层项目的pom里显式引入该依赖,或者调整
4. 检查类的打包情况和访问权限
有时候不是依赖的问题,而是底层项目的jar本身就没把报错的类打包进去!比如用Lombok生成的类、JAXB自动生成的类,可能因为插件配置不对,没被包含在jar里;另外,如果底层类是包访问权限(没有public修饰),上层项目在不同包下通过反射调用的话,也会出现运行时类找不到的情况。
- 排查动作:用
jar tf 底层项目.jar命令列出jar里的所有类,看看报错的类是不是存在;再检查该类的访问修饰符,确认是public。 - 解决方法:
- 如果类没打包,调整Maven插件配置(比如Lombok插件要确保在编译阶段生效),重新打包底层项目;
- 如果是访问权限问题,把类改成
public,或者调整上层项目的包结构(不推荐,最好还是用公开API)。
5. 清除Tomcat的缓存或重新部署
有时候就是Tomcat的缓存搞的鬼!比如之前部署的旧版本类还留在work目录里,和新部署的类冲突;或者war包解压时损坏了,导致部分类缺失。
- 解决方法:
- 停止Tomcat,删除
work目录和webapps下对应的项目文件夹; - 重新用
mvn clean package打包上层项目,确保war包完整,然后重新部署到Tomcat。
- 停止Tomcat,删除
内容的提问来源于stack exchange,提问作者Gábor Major




