jar包的多層級maven依賴的坑與正確傳遞方法




這個問題簡述起來就是項目加載jar包但是無法加載jar包的依賴

這是一個maven的特性嗎?


問題發生前

程序猿經常自己寫一些庫實現或收集常用的邏輯方法(算法和設計模式等等),以方便多個項目使用,避免重復編碼。本猿現在有這么一個庫,本猿把他叫 E庫E庫用maven做工程和生命周期管理,以便能用到其他java工程中。同時庫里面也引用了其他一些開源公共庫,使用或包裝他們以實現自己的功能。(如下是E庫部分依賴截圖)

E庫的依賴的一部分
E庫的依賴的一部分


本猿新建一個項目A,並引入這個自用的庫,如果項目人多會用私庫,多數情況不會超過5個人的,一般本猿會用項目中的文件夾做倉庫。在項目A的pom.xml中加入這個文件夾做的倉庫:

<repositories>
	<repository>
		<id>minimal-maven-repository</id>
		<url>file:///${project.basedir}/minimal-maven-repository</url>
		<layout>default</layout>
		<releases>
			<enabled>true</enabled>
		</releases>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
</repositories>

這里就用minimal-maven-repository這個文件夾做倉庫。


現在,在項目A根目錄執行如下命令把E庫部署到這個倉庫中:

VERSION=1.2.0-snapshot
mvn deploy:deploy-file -Dfile=/server/data/ejoker/target/ejoker-${VERSION}.jar -DgroupId=pro.jiefzz -DartifactId=ejoker -Dversion=${VERSION} -Dpackaging=jar -Durl=file:./minimal-maven-repository/ -DrepositoryId=minimal-maven-repository -DupdateReleaseInfo=true

如果用Nexus私庫的話,上面這一步相當於把jar發布到私庫,並在項目中引入私庫地址。

其中:

選項 用途
-Dfile 指明部署的庫的路徑
-DgroupId 設置庫的groupId
-DartifactId 設置庫的唯一artifactId
-Dversion 設置當前要部署庫的版本
-Dpackaging 部署的類型
-Durl 倉庫的位置,這里用項目里的一個文件夾做倉庫
-DrepositoryId 倉庫的id,這個選項在部署到中央倉庫時有用,這里自便
-DupdateReleaseInfo (字面意思理解)

如無意外大概會看到如下結果,即代表成功:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building willdelete 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ willdelete ---
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom (6 KB at 2.2 KB/sec)
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom (10 KB at 10.4 KB/sec)
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.jar
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.jar (245 KB at 199.1 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.jar
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.jar (427 KB at 21306.2 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom (398 B at 194.3 KB/sec)
Downloading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 153.3 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.570 s
[INFO] Finished at: 2019-09-26T21:29:43+08:00
[INFO] Final Memory: 8M/99M
[INFO] ------------------------------------------------------------------------

查看下minimal-maven-repository目錄看看:

Jiefzzs-MacBook-Pro:willdelete kimffy$ tree minimal-maven-repository/
minimal-maven-repository/
└── pro
    └── jiefzz
        └── ejoker
            ├── 1.2.0-snapshot
            │   ├── ejoker-1.2.0-snapshot.jar
            │   ├── ejoker-1.2.0-snapshot.jar.md5
            │   ├── ejoker-1.2.0-snapshot.jar.sha1
            │   ├── ejoker-1.2.0-snapshot.pom
            │   ├── ejoker-1.2.0-snapshot.pom.md5
            │   └── ejoker-1.2.0-snapshot.pom.sha1
            ├── maven-metadata.xml
            ├── maven-metadata.xml.md5
            └── maven-metadata.xml.sha1

4 directories, 9 files

是不是跟你在別的倉庫中看到的結構是一樣的啊,倉庫就是按這個結構裝jar的。


現在,可以在項目A的pom.xml中引入E庫以及一些項目中用到的庫了:

    <dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>1.7.16</version>
	</dependency>
    <dependency>
		<groupId>pro.jiefzz</groupId>
		<artifactId>ejoker</artifactId>
		<version>1.2.0-snapshot</version>
	</dependency>
    <dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
		<version>4.5.8</version>
	</dependency>

接下來,eclipse中

右鍵點擊項目 -> maven -> update project

正常通過沒毛病。


接下來在代碼中使用項目A的寫一段代碼,並在里面用上E庫

package pro.jiefzz.willdelete;

import pro.jiefzz.ejoker_support.rocketmq.DefaultMQConsumer;
import pro.jiefzz.ejoker_support.rocketmq.MQInstanceHelper;

/**
* Hello world!
*
*/
public class App 
{
    public static void main( String[] args )
    {
//        System.out.println( "Hello World!" );
        // 這個其實是E庫中創建rocketmq客戶端的一個助手類,沒什么特別的邏輯的。
        DefaultMQConsumer createDefaultMQConsumer = MQInstanceHelper.createDefaultMQConsumer("", "127.0.0.1:9876", null);
    }
}

問題發生了

然后運行項目App主類:

eclipse點擊運行App主類

鵝?! 找不到類?是本猿打開方式不對嗎? 命令中敲一次mvn -Dmaven.test.skip=true clean compile package

eclipse點擊運行App主類

-_-! 還真找不到啊。。。

java.lang.NoClassDefFoundError: org/apache/rocketmq/client/consumer/AllocateMessageQueueStrategy

這個明顯是rocketmq的,而這個rocketmq的依賴不是E庫帶着的嗎(參考上面的圖)?難道本猿還要在項目A的pom.xml中貼一次E庫的依賴嗎?(其實本猿是故意調用E庫中使用有依賴其他jar的代碼的😈)


為什么E庫的依賴沒有被加載到項目A中?

為什么會醬

終端里看一下依賴樹 mvn dependency:tree

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ willdelete ---
[INFO] pro.jiefzz:willdelete:jar:0.0.1-SNAPSHOT
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] +- pro.jiefzz:ejoker:jar:1.2.0-snapshot:compile
[INFO] \- org.apache.httpcomponents:httpclient:jar:4.5.10:compile
[INFO]    +- org.apache.httpcomponents:httpcore:jar:4.4.12:compile
[INFO]    +- commons-logging:commons-logging:jar:1.2:compile
[INFO]    \- commons-codec:commons-codec:jar:1.11:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

有點不好看,不要緊 大概就是 willdelete依賴了3個包,其中httpclient 下有3個依賴包,而junitejoker就直接是末端,沒有更下層的依賴了

eclipse看項目依賴樹

eclipse里面看到的是一個意思的。很明顯,E庫(就是這里的ejoker包)下應該有一些依賴啊(例如rocketmq客戶端的,以及前面貼了圖的)


這個問題以前就出過,只不過那時沒閑管他,直接把E庫的依賴往項目A里貼一次(相當於手動提供了😹)

今天刷了很久的Google沒找到(以前找過也沒找到),找到的都是把依賴的直接跟目標jar打到一起(不管是解壓后吧class放到一起還是裝到提個lib文件夾里面然后把classpath寫到META-INF/mainifest.mf里面,這兩殊途同歸,行話叫打胖包和打瘦包),都不是本猿要的。


其實問題出在上面那個deploy到本地倉庫的過程,
mvn deploy過程里有個參數 -DgeneratePom,默認值是true的 -_-**

那他干了些啥呢?看剛剛那個本地倉庫的目錄

Jiefzzs-MacBook-Pro:willdelete kimffy$ tree minimal-maven-repository/
minimal-maven-repository/
└── pro
    └── jiefzz
        └── ejoker
            ├── 1.2.0-snapshot
            │   ├── ejoker-1.2.0-snapshot.jar
            │   ├── ejoker-1.2.0-snapshot.jar.md5
            │   ├── ejoker-1.2.0-snapshot.jar.sha1
            │   ├── ejoker-1.2.0-snapshot.pom
            │   ├── ejoker-1.2.0-snapshot.pom.md5
            │   └── ejoker-1.2.0-snapshot.pom.sha1
            ├── maven-metadata.xml
            ├── maven-metadata.xml.md5
            └── maven-metadata.xml.sha1

4 directories, 9 files

看看里面的ejoker-1.2.0-snapshot.pom :

Jiefzzs-MacBook-Pro:willdelete kimffy$ cat minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>pro.jiefzz</groupId>
<artifactId>ejoker</artifactId>
<version>1.2.0-snapshot</version>
</project>
Jiefzzs-MacBook-Pro:willdelete kimffy$

這段按人話說就是:這是個包。然后。。 然后沒了。 沒了?! 是的,沒別的了,項目端的maven獲得的信息就只有這丁點兒。無語....

他不是E庫的pom.xml吧,是那個隱含的-DgeneratePom=true參數的傑作吧...

問題就是這里,maven不知道他還要依賴。一些純工具類庫沒有其他依賴的,這樣當然不會出問題,他不需要依賴,maven也沒為他加載依賴。也有些需要依賴的但是項目中同時又用到了的,似乎沒問題,但是只是恰巧遇上剛剛而已,如依賴log類最好理解了 大概率項目也用庫里也用。即便有依賴沒加載上,回頭再打個胖包也是可以的。

但是這不是本猿現在要的。


腫么辦才好

既然在倉庫里缺了pom.xml那就補上咯,再敲一次命令,其中補上參數-DgeneratePom=false,-Dfile=指向E庫的pom.xml,執行如下:

$ mvn deploy:deploy-file -Dfile=/server/data/ejoker/pom.xml -DgroupId=pro.jiefzz -DartifactId=ejoker -Dversion=${VERSION} -Dpackaging=pom -Durl=file:./minimal-maven-repository/ -DrepositoryId=minimal-maven-repository -DupdateReleaseInfo=true -DgeneratePom=false
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building willdelete 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ willdelete ---
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom (7 KB at 354.7 KB/sec)
Downloading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Downloaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 27.9 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 102.2 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.645 s
[INFO] Finished at: 2019-09-26T22:42:18+08:00
[INFO] Final Memory: 7M/123M
[INFO] ------------------------------------------------------------------------

再看看依賴樹:

eclipse看項目依賴樹

全部都出來了


再跑一下主類App :

輸出

不再是剛剛的錯誤 而是一個RuntimeException,也就是依賴問題已經被解決,(這個運行時異常是因為本猿在createDefaultMQConsumer的第三個參數傳入了null)


再附上一個Nexus私庫時如果想最終項目能夠繼承這個依賴的話應該是這樣的,下圖紅框的位置,同時上送你的jar和項目的pom.xml

輸出


有問題歡迎指正😂


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM