經驗之談
工作中,我們常常需要將基礎架構部門的 jar 包提供給業務部門的同事使用,那么,需要將 jar 包 deploy 到 nexus 私服上,網上資料不是很多,這里說一下具體細節。
首先,是打 jar 包,maven 默認是不會將依賴的 jar 打入到新包中的,而是通過 pom 文件進行構建。而現在流行的 SpringBoot 項目則將所有的 jar 包打進去,使其能夠快速部署。
通常,我們上傳到 Nexus 私服上的 jar 包不會包含其他的 jar 包,依賴關系依靠 pom 文件。
假設,你已經通過 package 命令生成了一個不包含其他的 jar 的 jar 包。那么就可以使用以下命令:
mvn deploy:deploy-file
-DgroupId={yourProject} \
-DartifactId={yourProject}\
-Dfile={yourFile}\ // jar 包路徑
-Durl={URL} \// 私服URL
-DrepositoryId=releases\
-Dpackaging=jar\ // 指定格式,如果不寫,一句 pom 文件中
-DpomFile=pom.xml // 指定該 jar 包的 pom 文件,如不指定,將生成一個默認的 pom——導致不可用
其中,比較關鍵的就是 -DpomFile=pom.xml
,如果你不指定的話,那么 maven 就會自動生成一個 pom ,但基本是一個空的 pom,依賴關系都沒有的 —— 這將導致,如果別人引用了你的 jar 包,並且需要使用依賴關系里的代碼,但卻找不到,就會拋出 NoClassDefFoundError 錯誤,因為編譯時沒有問題,但運行時卻找不到 class 文件。
deploy:deploy-file 插件有很多參數,想了解更多內容,可以參照官方文檔:https://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html#packaging。
意外收獲
關於 NoClassDefFoundError 和 ClassNotFoundException 的區別,因為查錯的時候,遇到了這個錯誤,所以查了一下:
- 前者是編譯成功,但運行時找不到 jar 包,通常是兩個相同的類,不同的版本,或者我上面的說的,jar 包里沒有依賴包,pom 里也沒有依賴關系,並且,相關的類也會 import 這個類。
- 后者通常發生在使用反射時,例如
Class.forName("cn.thinkinjava.Hello")
,反射的時候,是不會 import 這個類的,兩者的錯誤場景是不一樣的。
從后者是個Exception ,前者是個 error 就能看出,Java 容忍后者,不容忍前者,前者更多的是構建過程中的錯誤,而不是編碼過程中的錯誤,