最近在用 Springboot 开发项目 A,引了小伙伴开发的模块 B,本地起服务,运行的好好的,等部署到服务器上,一运行就报错:Caused by: java.lang.ClassNotFoundException。html
注:致使该错误的缘由有不少,好比:包冲突、类冲突、包不存在等,我这里只列举其中一种状况,毕竟坑了我半天的时间,我以为有必要分享出来。java
先看一个诡异的现象吧,我用别的工程 C 引用了一样的依赖 B,部署到服务器上,运行的好好的,就我这个工程不行?细看:apache
1)工程 C 部署到服务器上,/app/C-service/lib 下的 jar包是:api
B-api-1.0.0-20191224.024308-5.jar
B-dao-1.0.0-20191223.073120-2.jar
2)工程 C 部署到服务器上,/app/C-service/C-service.jar/META-INF/MANIFEST.MF,扫描路径是:服务器
lib/B-api-1.0.0-20191224.024308-5.jar
lib/B-dao-1.0.0-20191223.073120-2.jar
而:app
1)个人工程 A 部署到服务器上,/app/A-service/lib 下的 jar包是:maven
B-api-1.0.0-SNAPSHOT.jar
B-dao-1.0.0-SNAPSHOT.jar
2)个人工程 A 部署到服务器上,/app/A-service/A-service.jar/META-INF/MANIFEST.MF,扫描路径是:ide
lib/B-api-1.0.0-20191224.024308-5.jar
lib/B-dao-1.0.0-20191223.073120-2.jar
发现:MANIFEST.MF 中扫描的 jar 包路径和实际解压出来的 jar 包名称不一致(一个带时间戳,一个是 SNAPSHOT),因此扫描不到 jar 包,致使报错:Caused by: java.lang.ClassNotFoundException。spa
那么是什么缘由构成了这桩惨案呢?机缘巧合:code
1.我小伙伴的模块,deploy 时用的是 SNAPSHOT,如 1.0.0-SNAPSHOT,我在拉取 jar包时,拉到的是:B-api-1.0.0-20191224.024308-5.jar:
<dependency> <groupId>com.xxx.xxx</groupId> <artifactId>B-api</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency>
2.个人工程 A 本地能够跑,是由于那时候我没有打包 mvn clean package -Dmaven.test.skip=true,IDEA 本地运行项目时 jar 包扫描路径 和 实际拉取的 jar 包一致;当我打包后,解压出 A-service.zip 包,本地运行一样会报错;
3.问题在于工程 A 打包先后的区别,为何打包后:MANIFEST.MF 和 A-service.zip 解压后的 lib/ 目录下的 jar包 名称不一致?
4.最后经过比较工程 C 的配置文件和 A 的配置文件,找到不一样点:A工程的 assembly.xml 中多了一行:<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
<dependencySets> <dependencySet> <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping> <useProjectArtifact>false</useProjectArtifact> <outputDirectory>lib</outputDirectory> </dependencySet> </dependencySets>
5.把这行去掉,问题确实解决了。可是为何呢?拉下来的 jar 包、MANIFEST.MF 中扫描的 jar包带时间戳,总以为不够清秀、哪里不对劲。随后我以 outputFileNameMapping 为字眼找了下相关资料,果真找到了另一位老大哥:<useUniqueVersions>false</useUniqueVersions> ,这行配置是放在工程的 Service 模块(Application.java 启动类所在模块)的 pom.xml 中:
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>${main.class}</mainClass> <useUniqueVersions>false</useUniqueVersions> </manifest> </archive> <excludes> <exclude>*.yml</exclude> <exclude>*.properties</exclude> </excludes> </configuration> </plugin>
6.解释:
1)<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>,做用是在你打包的时候:lib/ 下的 jar 包能够重命名,好比原本应该是 B-api-1.0.0-20191224.024308-5.jar,经过这行配置后,jar包被重命名为:B-api-1.0.0-SNAPSHOT.jar;
2)<useUniqueVersions>false</useUniqueVersions>,做用是在你生成 MANIFEST.MF 文件时,lib/ 下的 jar包若是版本是 xxx-SNAPSHOT,要不要带惟一版本时间戳,若是你配置为 false(默认为 true),那么原本应该是 B-api-1.0.0-20191224.024308-5.jar,经过这行配置后,jar包被重命名为:B-api-1.0.0-SNAPSHOT.jar;
恰好:
1)工程 C 中 outputFileNameMapping,useUniqueVersions 都没配置,使用默认值,使得 lib/ 下的 jar包名称 和 MANIFEST.MF 下的扫描路径 jar包名称一致(都带时间戳);
2)而个人工程 A,不仅从哪里拷贝来的配置文件,配了 outputFileNameMapping (没带时间戳),但没配置 useUniqueVersions(带时间戳),致使不一致;
因此:这两个配置,要么都有,要么都没有,否则就会出现不一致,致使报错。
我我的以为,jar 包名称仍是不带时间戳更清秀些,因此我推荐 outputFileNameMapping,useUniqueVersions 都配置上,以下:
1.assembly.xml 中添加配置:<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
<dependencySets> <dependencySet> <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping> <useProjectArtifact>false</useProjectArtifact> <outputDirectory>lib</outputDirectory> </dependencySet> </dependencySets>
2.启动类 Application.java 所在模块的 pom.xml 中添加配置:<useUniqueVersions>false</useUniqueVersions>
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>${main.class}</mainClass> <useUniqueVersions>false</useUniqueVersions> </manifest> </archive> <excludes> <exclude>*.yml</exclude> <exclude>*.properties</exclude> </excludes> </configuration> </plugin>
Snapshot Workaround If you are using a SNAPSHOT version of Pippo as described in the Maven section, a small workaround is necessary due to a Maven bug: 1) Add <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping> to the dependencySet element inside assembly.xml 2) Add <useUniqueVersions>false</useUniqueVersions> to the maven-jar-plugin’s manifest section inside pom.xml
转载请注明出处哈,have a good time ~ : - )