急~爲啥我指定的的maven依賴版本沒有生效?不是最短路徑原則嗎?

女友他們項目用了 spring-boot,以 spring-boot-parent 做爲 parent:html

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

女友最近想用 elasticsearch 做爲搜索引擎,在項目中添加了依賴java

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

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

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版本是:springboot

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,依賴不是最短路徑原則麼?不該該以這個依賴爲準麼?elasticsearch

女友因而找我求助,本着面向「對象」,我立馬放下手頭工做幫忙查看。仔細一看,原來SpringBoot的DependencyManagement中,org.elasticsearch:elasticsearch已經被包含了(如下爲節選):maven

<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 其實已經考慮到用戶可能要換版本了,因此將版本放入了 &lt;properties/&gt;,properties 也具備最短路徑原則,因此能夠經過在你的項目根 pom 中的 properties 增長相同 key 修改版本:ide

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

全部能夠這麼替換的屬性, spring-boot 官方文檔已經列出了,參考官方文檔附錄:Version Propertiesspring-boot

也能夠經過 dependencyManagement 的最短路徑原則,經過在你的項目根 pom 中的增長想修改依賴的 dependencyManagement 便可:搜索引擎

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

最後,能夠記住下面的原則,就知道項目的依賴究竟是哪一個版本啦:.net

Maven依賴能夠分爲以下幾部分:

  1. 直接依賴,就是本項目 dependencies 部分的依賴
  2. 間接依賴,就是本項目 dependencies 部分的依賴所包含的依賴
  3. 依賴管理,就是本項目 dependency management 裏面的依賴
  4. parent 的直接依賴
  5. parent 的間接依賴
  6. parent 的依賴管理
  7. bom 的直接依賴(通常沒有)
  8. bom 的間接依賴(通常沒有)
  9. 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 塊零用錢啦,開心~

每日一刷,輕鬆提高技術,斬獲各類offer:

image

相關文章
相關標籤/搜索