maven依賴版本沒有按照最短路徑原則生效的解決方案

女朋友他們項目用瞭 spring-boot,以 spring-boot-parent 作為 parent:

<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.0.9</version>
</parent>

女朋友最近想用 elasticsearch 作為搜索引擎,在項目中添加瞭依賴

<dependency>
 <groupId>org.elasticsearch</groupId>
 <artifactId>elasticsearch</artifactId>
 <version>7.10.2</version>
</dependency>

寫好代碼,一跑,報類不存在異常:

 java.lang.NoClassDefFoundError: org/elasticsearch/common/xcontent/DeprecationHandler
 at com.lv.springboot.datasource.ClientUTis.main(ClientUTis.java:13)
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.common.xcontent.DeprecationHandler
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 ... 1 more

女朋友看瞭依賴mvn dependency:tree,發現依賴的elasticsearch版本是:

org.elasticsearch.client:elasticsearch-rest-high-level-client:7.0.1
|--org.elasticsearch:elasticsearch:5.6.16
|--org.elasticsearch.client:elasticsearch-rest-client:7.0.1
|--org.elasticsearch.plugin:parent-join-client:7.0.1
|--org.elasticsearch.plugin:aggs-matrix-stats-client:7.0.1
|--org.elasticsearch.plugin:rank-eval-client:7.0.1
|--org.elasticsearch.plugin:lang-mustache-client:7.0.1

女朋友很著急,明明指定瞭elasticsearch的依賴瞭啊,而且是項目的根 pom,依賴不是最短路徑原則麼?不應該以這個依賴為準麼?

女朋友於是找我求助,本著面向“對象”,我立馬放下手頭工作幫忙查看。仔細一看,原來SpringBoot的DependencyManagement中,org.elasticsearch:elasticsearch已經被包含瞭(以下為節選):

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.9.RELEASE</version>

<properties>
<elasticsearch.version>5.6.16</elasticsearch.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

spring-boot 其實已經考慮到用戶可能要換版本瞭,所以將版本放入瞭 <properties/>,properties 也具有最短路徑原則,所以可以通過在你的項目根 pom 中的 properties 增加相同 key 修改版本:

<properties>
<elasticsearch.version>7.10.2</elasticsearch.version>
</properties>

所有可以這麼替換的屬性, spring-boot 官方文檔已經列出瞭,參考官方文檔附錄:Version Properties

也可以通過 dependencyManagement 的最短路徑原則,通過在你的項目根 pom 中的增加想修改依賴的 dependencyManagement 即可:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.2</version>
</dependency>
</dependencies>
</dependencyManagement>

最後,可以記住下面的原則,就知道項目的依賴到底是哪個版本啦:

Maven依賴可以分為如下幾部分:

  • 直接依賴,就是本項目 dependencies 部分的依賴
  • 間接依賴,就是本項目 dependencies 部分的依賴所包含的依賴
  • 依賴管理,就是本項目 dependency management 裡面的依賴
  • parent 的直接依賴
  • parent 的間接依賴
  • parent 的依賴管理
  • bom 的直接依賴(一般沒有)
  • bom 的間接依賴(一般沒有)
  • bom 的依賴管理

可以這麼理解依賴:

1.首先,將 parent 的直接依賴,間接依賴,還有依賴管理,插入本項目,放入本項目的直接依賴,間接依賴還有依賴管理之前

2.對於直接依賴,如果有 version,那麼就依次放入 DependencyMap 中。如果沒有 version,則從依賴管理中查出來 version,之後放入 DependencyMap 中。key 為依賴的 groupId + artifactId,value為version,後放入的會把之前放入的相同 key 的 value 替換

3.對於每個依賴,各自按照 1,2 加載自己的 pom 文件,但是如果第一步中的本項目 dependency management 中有依賴的版本,使用本項目 dependency management的依賴版本,生成 TransitiveDependencyMap,這裡面就包含瞭所有的間接依賴。

4.所有間接依賴的 TransitiveDependencyMap, 對於項目的 DependencyMap 裡面沒有的 key,依次放入項目的 DependencyMap

5.如果 TransitiveDependencyMap 裡面還有間接依賴,那麼遞歸執行3, 4。

由於是先放入本項目的 DependencyMap,再去遞歸 TransitiveDependencyMap,這就解釋瞭 maven 依賴的最短路徑原則。

Bom 的效果基本和 Parent 一樣,隻是一般限制中,Bom 隻有 dependencyManagement 沒有 dependencies

解決瞭問題並且給妹子梳理明白之後,妹子答應這個月多給我 100 塊零用錢啦,開心~~~~~

以上就是maven依賴版本沒有生效的解決方案的詳細內容,更多關於maven依賴版本沒有生效的資料請關註WalkonNet其它相關文章!

推薦閱讀: