這個問題簡述起來就是項目加載jar包但是無法加載jar包的依賴
這是一個maven的特性嗎?
問題發生前
程序猿經常自己寫一些庫實現或收集常用的邏輯方法(算法和設計模式等等),以方便多個項目使用,避免重復編碼。本猿現在有這么一個庫,本猿把他叫 E庫
, E庫
用maven做工程和生命周期管理,以便能用到其他java工程中。同時庫里面也引用了其他一些開源公共庫,使用或包裝他們以實現自己的功能。(如下是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主類:
鵝?! 找不到類?是本猿打開方式不對嗎? 命令中敲一次mvn -Dmaven.test.skip=true clean compile package
-_-! 還真找不到啊。。。
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個依賴包,而junit
和ejoker
就直接是末端,沒有更下層的依賴了
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] ------------------------------------------------------------------------
再看看依賴樹:
全部都出來了
再跑一下主類App :
不再是剛剛的錯誤 而是一個RuntimeException,也就是依賴問題已經被解決,(這個運行時異常是因為本猿在createDefaultMQConsumer的第三個參數傳入了null)
再附上一個Nexus私庫時如果想最終項目能夠繼承這個依賴的話應該是這樣的,下圖紅框的位置,同時上送你的jar和項目的pom.xml
有問題歡迎指正😂