最常用且最精准的解决方式是直接在pom.xml中用<exclusions>切断不需要的传递依赖;需先用mvn dependency:tree -Dverbose或-Dincludes定位冲突源头,在引入该依赖的<dependency>块内精准排除,仅写groupId和artifactId,排除后须验证版本唯一性及功能完整性,并建议配合dependencyManagement统一版本。

直接在 pom.xml 中用 <exclusions> 切断不需要的传递依赖,是最常用也最精准的解决方式。关键不是“排除越多越好”,而是“排除得准、排得稳”。
明确谁引入了冲突版本
先运行命令定位源头:
-
mvn dependency:tree -Dverbose:显示所有被裁剪(omitted for conflict)和被忽略的节点,不漏隐藏路径 -
mvn dependency:tree -Dincludes=groupId:artifactId:聚焦查看某个包(如org.apache.logging.log4j:log4j-core)被哪些依赖层层带入
例如输出中看到:
[INFO] | \- org.springframework.boot:spring-boot-starter-logging:jar:2.7.18:compile
[INFO] | \- org.apache.logging.log4j:log4j-core:jar:2.17.2:compile
[INFO] \- com.example:legacy-sdk:jar:1.2.0:compile
[INFO] \- org.apache.logging.log4j:log4j-core:jar:2.11.2:compile (omitted for conflict)
说明 legacy-sdk 带来了旧版 log4j-core,而 Spring Boot 引入了新版——冲突就在这里,排除目标应是 legacy-sdk 的传递依赖。
在对应依赖块内写 exclusion
不是全局删包,而是“在哪引入的,就在哪排除”:
- 只写
<groupId>和<artifactId>,不用写<version> - exclusion 只作用于当前
<dependency>的传递链,不影响其他依赖 - 如果一个依赖多次出现(比如多个模块都用了 fastjson),需在每个声明处分别排除
示例:
立即学习“Java免费学习笔记(深入)”;
<dependency>
<groupId>com.example</groupId>
<artifactId>legacy-sdk</artifactId>
<version>1.2.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>排除后必须验证效果
排除不是一劳永逸,要确认它真正生效:
- 再次执行
mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-core - 检查输出里是否只剩一个版本(且是你期望的版本),且不再出现 omitted for conflict
- 启动应用,重点测试原本报错的功能点(如日志输出、JSON 序列化等),避免因排除导致功能缺失
注意:若排除后某功能异常(比如 legacy-sdk 内部硬编码调用了 log4j 2.11 特有 API),说明不能简单排除,需升级 SDK 或改用适配层。
配合 dependencyManagement 更稳妥
单纯 exclusion 容易遗漏或维护困难,建议搭配 <dependencyManagement>:
- 在父 POM 或当前 POM 的
<dependencyManagement>中声明统一版本(如 log4j-core 2.20.0) - 这样即使某个依赖没被排除,Maven 也会按管理版本拉取,降低冲突概率
- exclusion + version lock 双保险,既切断干扰路径,又兜底保障版本一致性


















