記一次 Maven 打包后,第三方無法使用的排查記錄
你好,我是悟空。
本文主要內容如下:
目錄
前言
最近遇到一個需求:
寫一個工具類的 JAR 包,然后提供給第三方調用其中的類方法。(前提:第三方無法共用我們項目的私有倉庫)
期間遇到了一些問題:
- 第三方引入 JAR 包后,無法import。
- 第三方引入 JAR 包后,缺少 JAR 包中的其他依賴。
本篇做個記錄,希望能幫助到其他小伙伴。
本篇既然涉及到 Maven,這里先總結下 Maven 的常用命令。對 Maven 命令比較熟悉的同學可以跳過這小節。
一、Maven 常見命令
當我們創建好一個 Maven 工程時,IDEA 開發工具的右側就會自動出現 Maven 命令。
Maven 操作
我們用鼠標雙擊下就可以運行了,也可以通過命令行來執行
下面介紹這幾種命令的區別。
clean(常用)
刪除項目路徑下的 target 文件,但是不會刪除本地的maven倉庫已經生成的 JAR 文件。
validate
驗證工程正確性,所需信息是否完整。
compile
編譯。會在你的項目路徑下生成一個target目錄,在該目錄中包含一個classes文件夾,里面全是生成的class文件。
test
執行單元測試。
package(常用)
將工程文件打包為指定的格式,例如 JAR,WAR 等(看你項目的 pom文件,里面packaging 標簽就是來指定打包類型的)。
這個命令會在你的項目路徑下一個target目錄,并且擁有compile命令的功能進行編譯,同時會在target目錄下生成項目的 jar/war文件。
如果a項目依賴于b項目,打包b項目時,只會打包到b項目下target下,編譯a項目時就會報錯,因為找不到所依賴的b項目,說明a項目在本地倉庫是沒有找到它所依賴的b項目,這時就用到 install 命令。
verify
核實,主要是對 package 檢查是否有效、符合標準。
install(常用)
將包安裝至本地倉庫,以讓其它項目依賴。
該命令包含了 package 命令功能,不但會在項目路徑下生成 class 文件和 jar 包,同時會在你的本地maven倉庫生成 jar 文件,供其他項目使用(如果沒有設置過maven本地倉庫,一般在用戶 /.m2 目錄下。如果 a 項目依賴于 b 項目,那么 install b 項目時,會在本地倉庫同時生成 pom 文件和 jar文件,解決了上面打包 package出錯的問題)。
build
建造。功能類似compile,區別是對整個項目進行編譯。
與 compile區別及特點:是對整個工程進行徹底的重新編譯,而不管是否已經編譯過。
Build過程往往會生成發布包,這個具體要看對 IDE 的配置了,Build在實際中應用很少,因為開發時候基本上不用,發布生產時候一般都用ANT等工具來發布。Build 因為要全部編譯,還要執行打包等額外工 作,因此時間較長。
site
生成項目的站點文檔。
deploy(常用)
部署。將 jar 包部署到遠程倉庫,通常是私有倉庫。而且包含了 install 命令的功能。
二、打包后,無法 import?
下面介紹一下我用常規打包方式遇到的問題。
我通過 IDEA 工具創建了一個 SpringBoot 項目,然后 pom.xml 文件中會自動引入一個打包插件,如下圖所示:
然后我執行 maven package 命令,會在項目的 target 目錄生成一個 JAR 包。如下圖所示:
然后我做了以下事情:
把這個 JAR 包拷貝出來,發給了第三方。
讓第三方拷貝到他們自己的本地項目中。這里是在項目的根目錄創建了一個 libs 目錄,然后將 jar 包放到 libs 目錄中。
讓第三方在 pom 依賴中引入這個依賴包。
scope 指定為 system,表示引入指定路徑(systemPath配置)下的 JAR 包。
看起來這么做沒問題了,但是當我們 import 這個 JAR 包下的類時,就會報錯。如下圖所示:
很奇怪,這里為什么會報錯呢??
先看下這個 JAR 包是否引入了。如下所示,可以看到確實是正確引入了,沒有報錯。
通過 research,發現這個打包插件打出來的 JAR 包,是供執行的,也就是可以通過 java -jar 命令來運行這個 JAR 包,并不能給第三方來引用使用。
解決方案:換一個打包插件 maven-compiler-plugin。
再次打包發給第三方,發現 import 不報錯了。
但是又報另外一個錯,我們接著往下看。
三、缺少其他 Jar 包依賴?
報錯信息如下:
通過這個信息,可以想到是不是我提供的 JAR 包中引入了這個 commons-codec 依賴,而 JAR 包文件中又不包含這個依賴。
看下這個 JAR 文件的大小,只有 14 KB, 而 commons-codec 的包大小為 339 KB,說明這個 JAR 包確實不包含 common-codec 依賴。
解決方案:
將其他依賴包打入到這個 JAR 包里面(推薦)。
第三方自己引入其他依賴包。(麻煩了第三方,要第三方一個個引入)
那如何將依賴的包打進這個 JAR 包里面呢?
這里還要引入一個打包插件:maven-assembly-plugin,如下所示。(省略了部分標簽)
然后還要用插件打包的方式:assembly:assembly
然后target目錄下會多出一個包,帶了一個后綴:jar-with-dependencies
這個包的文件的大小比較大,有 15.4 M。
發給第三方再次引入后,不再報錯了。
我們來看下這個包里面有什么東西,在 META-INF/maven 目錄下可以看到 commons-codec 依賴包,說明確實將這個依賴包打進去了。
而之前打的包,是沒有這個目錄的。
至此,排查結束。
參考資料:
??https://blog.csdn.net/Shangxingya/article/details/114810454??
??https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html??
關于我
8 年互聯網開發經驗,擅長微服務、分布式、架構設計。目前在一家大型上市公司從事基礎架構和性能優化工作。
InfoQ 簽約作者、藍橋簽約作者、阿里云專家博主、51CTO 紅人。