加-Dverbose才能看到依赖冲突,因默认裁剪重复依赖;冲突表现为同groupId:artifactId多路径不同version;生效版本由路径最短优先、声明顺序次之决定。

mvn dependency:tree 看不到冲突?先加 -Dverbose
默认执行 mvn dependency:tree 会自动裁剪重复依赖,看起来干净,但实际掩盖了冲突。真正要定位版本打架,必须加 -Dverbose 参数:
-
mvn dependency:tree -Dverbose:显示所有路径,包括被忽略的间接依赖 - 冲突表现为同一
groupId:artifactId出现在多条路径中,且version不同(比如com.fasterxml.jackson.core:jackson-databind:2.13.4和2.15.2) - 注意看输出末尾的「omitted for conflict」提示——它只告诉你“被裁掉了”,但不告诉你谁赢了、为什么赢
冲突到底谁生效?看 Maven 的“最近原则”和声明顺序
Maven 不是随机选版本,而是按两层规则决定最终使用的 JAR:
- 第一优先级:依赖路径最短者胜出(例如 A → B → C → D.jar 和 A → E → D.jar,后者路径更短,
D.jar版本以 E 声明的为准) - 第二优先级:路径长度相同时,以
pom.xml中<dependencies></dependencies>的**声明顺序**为准——靠前的优先保留 - 这个规则无法绕过,
<exclusion></exclusion>或<dependencymanagement></dependencymanagement>只能干预,不能推翻该逻辑
排除冲突依赖用 ,但别盲目删
在你自己的 pom.xml 里对某个依赖做排除,语法简单,但容易引发新问题:
- 写法示例:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </exclusion> </exclusions> </dependency> - 风险点:排除后,若其他依赖仍需要该 JAR 的旧版,可能报
NoClassDefFoundError或NoSuchMethodError - 更稳妥的做法是配合
<dependencymanagement></dependencymanagement>统一锁定版本,而不是到处<exclusion></exclusion>
用 mvn dependency:tree -Dincludes 定向排查特定包
项目大了,全量树太长。想快速确认某个库是否被多个版本引入,直接过滤:
mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind-
mvn dependency:tree -Dincludes=:slf4j-api(冒号开头表示忽略 groupId,匹配任意组织下的 artifactId) - 配合
grep更高效:mvn dependency:tree -Dverbose | grep "jackson-databind" - 注意:-Dincludes 不支持正则,只支持
groupId:artifactId或:artifactId格式
真正麻烦的不是看到冲突,而是某个传递依赖悄悄升级了 minor 版本,接口行为却变了——比如 Jackson 2.15 对空字符串反序列化策略收紧,而你代码里没做 null check。这种时候,dependency:tree 只能帮你定位到哪来的版本,具体是否兼容得靠测试覆盖和日志验证。

















