You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Maven多模块项目部署Tomcat7时部分类报ClassNotFoundException

解决Tomcat7部署Maven多模块项目时部分类加载失败的思路

这种部分类能正常加载、部分报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跳过加载它。

3. 确认Maven打包时的依赖遗漏或重复

有时候Maven的依赖传递会“掉链子”——比如底层项目的某个模块没被正确引入到上层,或者有依赖排除规则把必要的类给排除了;另外,如果上层war里存在多个版本的同一个jar,也会导致类加载逻辑混乱。

  • 排查动作
    • mvn dependency:tree > dependency.log导出上层项目的依赖树,搜索报错类所在的jar,看看是不是被排除了;
    • 解压上层项目的war包,查看WEB-INF/lib目录,确认底层项目的jar存在,且没有重复的jar(比如同时有xxx-1.0.jarxxx-2.0.jar)。
  • 解决方法
    • 如果依赖被排除了,在上层项目的pom里显式引入该依赖,或者调整<exclusions>规则;
    • 如果有重复jar,用<exclusions>把多余的版本排除掉,确保只保留需要的那个。

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。

内容的提问来源于stack exchange,提问作者Gábor Major

火山引擎 最新活动