为何多模块Maven项目依赖冲突时会使用旧版本?
Maven依赖冲突:为啥testA选了commons-lang3 3.1而非3.4?
嘿,这个问题我之前踩过坑,核心是Maven的**依赖调解(Dependency Mediation)**规则在搞事情,咱们一步步拆解明白:
1. 为啥你的testA用了3.1版本?
很多人误以为Maven会自动选版本号最高的依赖,但其实它的默认优先级是路径最短优先(官方叫「Nearest Definition」),不是版本优先。咱们梳理下你的依赖链:
- commons-lang3:3.1的路径:
testA → vaadin-client-compiler → commons-lang3:3.1(只隔了1层依赖,路径长度2) - commons-lang3:3.4的路径:
testA → testB → commons-lang3:3.4(隔了2层依赖,路径长度3)
因为3.1的路径更短,Maven就默认挑了它,这就是你看到不符合预期结果的原因。要是两个依赖路径长度一样,Maven才会看你在pom里的声明顺序,先写的那个依赖带的版本会被选中。
2. 为啥在testB版本里加[]能解决问题?
你说的在testB版本里加[],应该是指用精确版本范围声明(比如<version>[3.4]</version>),本质是你通过这种方式告诉Maven:「不管别的规则,就用3.4这个版本」。版本范围[3.4]表示必须匹配这个精确版本,Maven解析时会优先遵循这个明确要求,直接覆盖了原本的路径优先规则。
3. 有没有不用强制,让Maven自动选3.4的办法?
Maven本身没「自动选最高版本」的默认规则,但有几个更优雅的方式能让3.4被选中:
- 在testA里直接依赖commons-lang3:3.4:这样它的路径长度就变成1(
testA → commons-lang3:3.4),比3.1的路径更短,Maven自然会选这个版本。 - 用父pom的
<dependencyManagement>统一版本:在父项目的<dependencyManagement>块里声明commons-lang3的版本为3.4,所有子模块都会自动遵循这个版本,不管依赖链里的其他版本声明。 - 排除vaadin-client-compiler里的commons-lang3:在testA对vaadin-client-compiler的依赖里加
<exclusions>,把它带的3.1版本排除掉,这样Maven就只能用testB带的3.4版本了。
内容的提问来源于stack exchange,提问作者Black Trans Woman




