急~为啥我指定的的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

相关文章
相关标签/搜索