背景:
A应用maven打包没问题,但是启动报错ClassNotFound,而且报找不到的这个类并不是A应用的,是C应用的。
排查pom依赖发现A应用依赖B应用的一个jar包,B应用依赖了C应用的jar包
在A应用的pom:
<dependency>
<groupId>com.lyc.B</groupId>
<artifactId>lyc-common-sdk</artifactId>
<version>20240730-SNAPSHOT</version>
</dependency>
在B应用的pom:
<dependency>
<groupId>com.lyc.C</groupId>
<artifactId>lyc-cc</artifactId>
<version>20240730-SNAPSHOT</version>
</dependency>
开始都是这样没有设置scope,启动正常,后来被别人修改了B应用的pom,添加了scope修改后如下:
<dependency>
<groupId>com.lyc.C</groupId>
<artifactId>lyc-cc</artifactId>
<version>20240730-SNAPSHOT</version>
<scope>provided</scope><!--这行是后来添加导致启动报错的-->
</dependency>
但是在A应用里面没有做任何修改,项目启动报错。
原因分析:
当在B应用的POM中将C应用的依赖范围设置为provided时,这意味着Maven认为C应用的依赖在运行时(如在部署到容器中时)会被外部提供,因此在打包A应用时,Maven不会将C应用的依赖包含进去。
具体来说:
provided范围的依赖仅在编译和测试阶段可用,但在打包(如jar或war)和运行阶段不会被包含在内。
当A应用依赖于B应用时,A应用会间接地依赖于B应用所声明的所有依赖,除了那些范围被标记为test或provided的依赖。
因此,如果A应用需要使用C应用中的类,而B应用将C应用的依赖范围设置为了provided,那么在A应用的运行环境中,如果没有手动提供C应用的JAR文件,A应用就会因为找不到C应用中的类而抛出ClassNotFoundException。
解决方法:
1、修改B应用的依赖范围
将C应用的依赖范围从provided改为compile,这样在A应用打包时,C应用的依赖也会被包含进来。
2、在A应用中显式添加C应用的依赖
即使B应用将C应用的依赖范围设为provided,A应用也可以在其POM中显式添加C应用的依赖,这样可以确保C应用的依赖在A应用的构建过程中被正确包含。
3、提供C应用的JAR文件:
如果你确定在运行A应用的环境中(如Tomcat、Jetty等服务器)已经包含了C应用的JAR文件,那么可以保持B应用中C应用依赖的provided范围不变,但需要确保服务器的类路径中确实包含了C应用的JAR。
我这里采用的第二种方式,在A应用中将C应用的依赖显示添加后重新打包启动正常了。