当前位置: 首页 > 知识库问答 >
问题:

通过maven构建的java项目,各依赖的版本是如何确定的?

皇甫学海
2024-07-26

我在java项目中使用maven管理依赖。其中借助依赖工具查看,commons-codec的版本是1.16.0。
最终构建出来的jar包中也是1.16.0版本。
image.png

但是我通过idea自带的依赖分析工具查看,commons-codec有两个来源,根据颜色,1.16.0版本应该是是在poi中指定的
image.png
但是poi-4.1.2中指定的却是1.13版本
image.png
我又查看了httpclient中的配置,是1.9版本的commons-codec。这里是因为httpclient是继承自httpcomponents-client,httpcomponents-client中配置了1.9
image.png
所以我想知道为什么最终是1.16版本的commons-codec

共有2个答案

丁学
2024-07-26

依赖管理有多种方案,java采用的是扁平化依赖管理方案,也就是所有的依赖最终会被拉平。例如依赖树如下:

.
`-- A
    `-- D
    `-- C (v1)
`-- B
    `-- C (v2)

最终所有依赖被拉平:

.
`-- A
`-- B
`-- C (v2)
`-- D

多个依赖版本如果冲突,则高版本覆盖低版本,称为版本覆盖。

当然扁平化依赖管理并非唯一依赖解决方案,nodejs采用树形依赖+扁平依赖结合。版本相同则扁平化节省空间,版本冲突则树形依赖

徐麒
2024-07-26

Maven依赖决策

只有两个原则:

  1. 最短路径优先
  2. pom中先声明的优先

比如你问题中的commons-codec(大概举例,没太看清楚)
路径1:kc-common-->aliyun-sdk-oss-->http-client-->commons-codec
路径2:kc-common-->poi-ooxml-->poi-->commons-codec

你这两个路径长短一样,就会看aliyun-sdk-osspoi-ooxmlkc-common中的声明顺序,目前大概率是aliyun-sdk-oss在前

version问题

httpcomponents-client中配置了1.9
poi-4.1.2中指定的是1.13版本
最终是1.16.0

1.看你的pom是不是有<parent>标签,比如声明了spring-boot-parent,这里面会声明 version,会将整个项目中依赖的version全部统一为声明的版本
2.如果有<parent>标签,并且声明的version不是1.16.0,那你看自己的pom中是不是写了<properties>定义,覆盖了<parent>中的version,会以你定义的为准
3.查看当前pom是不是声明了<dependencyManagement>统一管理了version
4.是否使用了三方的bom来管理了版本,三方bom依赖会定义一系列version来统一版本
5.如果有多个bom对同一个库进行了版本管理,先声明的版本会统一整个项目的版本

确定version

1.你可以在idea安装Maven Helpher插件,通过Dependency Analyzer标签的All Dependencies as Tree来查看红色的依赖
2.在项目启动类main里写某个Jar里面具体的一个类,import进去,点击到源码,点击Project栏,点击Select Opened File就可以确定运行时具体决策的jar是哪个版本

 类似资料:
  • 我有一个包含多个子项目的根项目。最初,我们将这些项目作为独立的Maven项目保留,但我意识到Gradle更适合我使用。但是对于其中一个子项目,我们宁可不将其转换为Gradle项目,而将其保留为Maven项目。 root/build.gradle root/common.gradle root/api/pom.xml

  • 我正在尝试将我的项目从gradle构建转换为maven构建。我可以从maven生成war文件,但是maven中的一些依赖项JAR的版本与Gradle的版本不同。 问题1:为什么上述罐子的版本不一样? 问题2:为什么使用Gradle构建的战争有“cglib-2.2.1-v20090111.jar”,而使用Maven构建的战争却没有?

  • 我用我的真实情况来说明问题。 我使用logback 1.0.1进行日志记录,它包含SLF4J 1.6.4作为依赖项。我还为遗留日志API(Java . util . logging、log4j和commons-logging)使用SLF4J API桥,它们不是显式的依赖关系。这些也必须(最好)是版本1.6.4。 为了使我的pom.xml尽可能整洁和无错误,我想强制这些API桥接器与SLF4J版本相

  • 你可以在同一个构建里加入项目之间的依赖, 举个例子, 一个项目的 JAR 文件被用来编译另外一个项目. 在 api 构建文件里我们将加入一个由 shared 项目产生的 JAR 文件的依赖. 由于这个依赖, Gradle 将确保 shared 项目总是在 api 之前被构建. Example 7.13. 多项目构建 - 项目之间的依赖 api/build.gradle dependencies {

  • 我想知道下面是否可行以及如何实现。 我正在学习Spring boot的教程,其中提到我们可以有一个父依赖项。 然后定义没有版本号的依赖项。 这将在项目依赖项中添加依赖项版本1.5.6。释放sping-boot-starter和sping-boot-starter-web。 就像那样,我想找到什么是<代码> Spring-上下文 spring-jdbc Spring测试 谢谢!

  • 假设<code>B:1.0.1,但是子项目应该依赖于<code>A:1.2(有意覆盖传递依赖性)。 很容易发现 ,并从它的所有子POM中删除样板文件。不幸的是,下面的设置导致在最终的工件中使用两个版本:< code>A:1.0.1(作为< code>B:1.0.1的依赖项)和< code>A:1.0.2(来自父pom中的显式声明)。 如何在所有子项目中强制使用< code>A:1.0.2版本,并在