SpringBoot项⽬本地运⾏⽆异常,部署到Linux服务器运⾏报错:
java.lang。。。
⼀背景
最近在⽤ Springboot 开发项⽬ A,引了⼩伙伴开发的模块 B,本地起服务,运⾏的好好的,等部署到服务器上,⼀运⾏就报错:Caused by:
java.lang.ClassNotFoundException。
注:导致该错误的原因有很多,⽐如:包冲突、类冲突、包不存在等,我这⾥只列举其中⼀种情况,毕竟坑了我半天的时间,我觉得有必要分享出来。
⼆原因
先看⼀个诡异的现象吧,我⽤别的⼯程 C 引⽤了同样的依赖 B,部署到服务器上,运⾏的好好的,就我这个⼯程不⾏?细看:
1)⼯程 C 部署到服务器上,/app/C-service/lib 下的 jar包是:
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
⽽:
1)我的⼯程 A 部署到服务器上,/app/A-service/lib 下的 jar包是:
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,扫描路径是:
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。
那么是什么原因构成了这桩惨案呢?机缘巧合:
1.我⼩伙伴的模块,deploy 时⽤的是 SNAPSHOT,如 1.0.0-SNAPSHOT,我在拉取 jar包时,拉到的是:B-api-1.0.0-20191224.024308-5.jar:
<dependency>
<groupId&x</groupId>
<artifactId>B-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
2.我的⼯程 A 本地可以跑,是因为那时候我没有打包 mvn clean package -st.skip=true,IDEA 本地运⾏项⽬时 jar 包扫描路径和实际拉取的 jar 包⼀致;当我打包后,解压出 A-service.zip 包,本地运⾏同样会报错;
3.问题在于⼯程 A 打包前后的区别,为什么打包后:MANIFEST.MF 和 A-service.zip 解压后的 lib/ ⽬录下的 jar包名称不⼀致?
4.最后通过⽐较⼯程 C 的配置⽂件和 A 的配置⽂件,到不同点:A⼯程的 l 中多了⼀⾏:<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${sion}</outputFileNameMapping>
<dependencySets>
<dependencySet>
  <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${sion}</outputFileNameMapping>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
5.把这⾏去掉,问题确实解决了。但是为什么呢?拉下来的 jar 包、MANIFEST.MF 中扫描的 jar包带时间戳,总觉得不够清秀、哪⾥不对劲。随后我以outputFileNameMapping为字眼了下相关资料,果然到了另外⼀位⽼⼤哥:<useUniqueVersions>false</useUniqueVersions> ,这⾏配置是放在⼯程的Service 模块(Application.java 启动类所在模块)的 l 中:
<!-- 打包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}.${sion}</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 都配置上,如下:
l 中添加配置:<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${sion}</outputFileNameMapping>
<dependencySets>
<dependencySet>
maven打包本地jar包
<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${sion}</outputFileNameMapping>
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
2.启动类 Application.java 所在模块的 l 中添加配置:<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>
四参考资料
1)Apache Assembly:
2)Pippo Deployment:
出⾃:Pippo Deployment:
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?}.${sion}</outputFileNameMapping> to the dependencySet element l
2) Add <useUniqueVersions>false</useUniqueVersions> to the maven-jar-plugin’s manifest section l
转载请注明出处哈,have a good time ~ : - )

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。