最近在用 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 ~ : - )