惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Spread Privacy
Spread Privacy
H
Hacker News: Front Page
PCI Perspectives
PCI Perspectives
Webroot Blog
Webroot Blog
罗磊的独立博客
H
Heimdal Security Blog
TaoSecurity Blog
TaoSecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
大猫的无限游戏
大猫的无限游戏
月光博客
月光博客
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
Last Week in AI
Last Week in AI
美团技术团队
Help Net Security
Help Net Security
The Hacker News
The Hacker News
C
Cisco Blogs
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
The Register - Security
The Register - Security
IT之家
IT之家
WordPress大学
WordPress大学
Jina AI
Jina AI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Help Net Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
NISL@THU
NISL@THU
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
Scott Helme
Scott Helme
V
Vulnerabilities – Threatpost
B
Blog
T
Tenable Blog
博客园 - 三生石上(FineUI控件)
T
The Exploit Database - CXSecurity.com
S
Security Affairs
小众软件
小众软件
Hacker News: Ask HN
Hacker News: Ask HN
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
W
WeLiveSecurity
A
Arctic Wolf
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence

沉迷在 - Java.li - 无法自拔

Spring Boot启动报错 Failed to configure a DataSource 解决办法 给网站加一条会动的人群横幅:Little People 动画组件 Demo - 沉迷在 - Java.li - 无法自拔 【soso.re】聚合热榜 | CloudflareWorkers部分接口失效的排查与代理方案 - 沉迷在 - Java.li - 无法自拔 Spring Boot 2升级到Spring Boot 3完整指南:JDK17、javax迁移jakarta、依赖兼容与常见报错 - 沉迷在 - Java.li - 无法自拔 随机小姐姐视频 - 沉迷在 - Java.li - 无法自拔 Spring Boot与JDK版本兼容表:Spring Boot 2.x / 3.x / 4.x应该用哪个Java版本? - 沉迷在 - Java.li - 无法自拔 No compiler is provided in this environment解决办法:JDK、JRE、Maven与IDEA排查 - 沉迷在 - Java.li - 无法自拔 置身钉内|含全文 PDF - 沉迷在 - Java.li - 无法自拔 javac不是内部或外部命令怎么解决?JDK、JAVA_HOME和Path完整排查 Windows配置JAVA_HOME后不生效怎么办?java -version显示旧版本解决办法 Maven Could not transfer artifact 下载失败解决:settings.xml、国内镜像、本地缓存与代理排查 JSON转Java实体类完整教程:对象、数组、嵌套结构与LocalDateTime处理 Windows安装JDK 8 / 17 / 21 / 25完整教程:JAVA_HOME环境变量配置与验证 IDEA下载JDK很慢怎么办?手动配置本地JDK完整教程 Java版本号与class文件major version对照表:Unsupported class file major version 52 / 55 / 61 / 65 / 69 / 70 Gradle国内镜像配置教程:init.gradle、repositories与Wrapper加速完整指南 Maven国内镜像settings.xml配置大全:阿里云、腾讯云、华为云、清华源 Java开发者必备工具箱 2026年Java行情深度解读:就业真实现状、语言排名与开发者破局指南 如何防止服务器被暴力破解?2026年最全的5层防护实战指南 Go-RSS-Hub:我用 Go 搭了一个可扩展的 RSS 聚合服务 Vibe Coding 实战复盘 2026年全球十大顶级大语言模型横向对比报告 万能插座与十八般兵器:MCP 和 Skill 解决MySQL ONLY_FULL_GROUP_BY 模式导致的 SQL 语法错误 记一次处理服务器被暴力破解(含黑名单IP) Vibe Coding:一名“古法程序员”的使用反思与未来思考 .li后缀续费的特殊性(某些顶级域名在到期前可能被提前删除) 浅谈域名后缀以及市场前景 咖啡与编程 超越基础的编程智慧
Maven依赖冲突怎么排查?dependency:tree、exclusions与版本统一完整教程 - 沉迷在 - Java.li - 无法自拔
HiF · 2026-07-10 · via 沉迷在 - Java.li - 无法自拔

最后更新:2026-07-10
适用场景:Maven 依赖冲突、Jar 包版本冲突、NoSuchMethodError、ClassNotFoundException、NoClassDefFoundError、dependency:tree 使用、exclusions 排除依赖、dependencyManagement 统一版本

Java 项目里很多奇怪报错,表面看是代码问题,实际可能是 Maven 依赖冲突。

常见现象包括:

本地能跑,服务器不能跑
IDEA能跑,打包后不能跑
升级一个依赖后,另一个功能突然报错
NoSuchMethodError
ClassNotFoundException
NoClassDefFoundError
ClassCastException
BeanCreationException
Failed to instantiate

尤其是 Spring Boot、MyBatis、Jackson、Netty、Guava、SLF4J、Logback、Tomcat、Elasticsearch、Redisson、Dubbo、ShardingSphere 等依赖比较多的项目,很容易遇到版本冲突。

Maven 会自动引入传递依赖,也就是你引入 A,A 又依赖 B,B 又依赖 C,最终这些依赖都会进入你的项目 classpath;Maven 官方文档也说明,传递依赖会让依赖图快速变大,因此 Maven 提供了依赖调解、依赖管理、optional、exclusions 等机制来控制最终进入项目的依赖。(Apache Maven)

本文整理一套 Maven 依赖冲突排查流程,包括:

dependency:tree 怎么用
如何定位冲突依赖来源
如何排除传递依赖
如何用 dependencyManagement 统一版本
如何排查 NoSuchMethodError / ClassNotFoundException
Spring Boot 项目如何避免乱改版本
IDEA 中如何查看 Maven 依赖图

一、先说结论:Maven依赖冲突排查顺序

遇到 Maven 依赖冲突,建议按这个顺序处理:

1. 先看完整报错,确认是类找不到、方法找不到,还是版本不兼容
2. 用 mvn dependency:tree 查看完整依赖树
3. 用 -Dincludes 过滤目标依赖
4. 找到冲突 Jar 是被哪个依赖传递进来的
5. 判断应该升级、降级、排除,还是统一版本
6. 用 exclusions 排除不需要的传递依赖
7. 用 dependencyManagement 统一依赖版本
8. Spring Boot 项目优先使用官方 BOM,不要随便覆盖核心依赖版本
9. 执行 mvn clean test / mvn clean package 验证
10. 如果仍然异常,再检查打包结果、运行环境和服务器 classpath

不要一上来就做这些事:

直接删除整个 .m2 仓库
随便升级所有依赖到最新版
在 pom.xml 里到处写 exclusions
强行覆盖 Spring Boot 管理的版本
只看 IDEA 红不红,不看 dependency:tree

依赖冲突排查的核心是:

先确认最终生效的是哪个版本
再确认它是从哪里来的
最后决定怎么处理

二、什么是Maven依赖冲突?

简单说,Maven 依赖冲突就是:

项目中多个依赖同时需要同一个 Jar 的不同版本

例如:

A 依赖 guava 18.0
B 依赖 guava 32.1.3-jre

最终项目里只能有一个主要版本进入 classpath。问题是,如果 Maven 最终选了旧版本,而你的代码或某个框架需要新版本,就可能出现:

NoSuchMethodError
ClassNotFoundException
NoClassDefFoundError

Maven 的依赖调解规则中,遇到多个版本时会选择距离项目更近的版本,也就是“nearest definition”;如果两个版本深度相同,先声明的依赖优先。官方文档还说明,如果你想保证某个版本,可以在项目 POM 中显式声明该依赖版本。(Apache Maven)


三、常见依赖冲突报错

1. NoSuchMethodError

典型报错:

java.lang.NoSuchMethodError: 
com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V

含义:

运行时加载到了某个类
但这个类里没有当前代码需要调用的方法

常见原因:

编译时使用的是新版本 Jar
运行时加载的是旧版本 Jar

这是典型版本冲突。


2. ClassNotFoundException

java.lang.ClassNotFoundException: com.example.SomeClass

含义:

运行时找不到某个类

常见原因:

依赖没有被打进包
scope 写错
依赖被排除了
运行环境缺少 Jar
容器中依赖和项目依赖不一致

3. NoClassDefFoundError

java.lang.NoClassDefFoundError: com/example/SomeClass

含义:

编译时可能能找到类,但运行时找不到

常见原因:

依赖未打包
依赖 scope 不对
运行环境缺少 Jar
版本冲突导致类不存在

4. ClassCastException

java.lang.ClassCastException: class A cannot be cast to class A

这种看起来很奇怪,两个类名一样还不能转换,通常可能是:

同一个类被不同 ClassLoader 加载
项目和容器里存在重复 Jar
插件或应用服务器自带依赖与项目依赖冲突

四、第一步:用 dependency:tree 查看依赖树

最常用命令:

mvn dependency:tree

Maven Dependency Plugin 官方文档说明,dependency:tree 用来查看当前项目正在构建时解析出来的依赖层级,也就是 Maven 构建过程实际使用的依赖树。(Apache Maven)

输出示例:

[INFO] com.example:demo:jar:1.0.0
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:3.5.15:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:3.5.15:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-databind:jar:2.19.2:compile
[INFO] +- com.example:some-sdk:jar:1.0.0:compile
[INFO] |  \- com.fasterxml.jackson.core:jackson-databind:jar:2.13.5:compile

这种情况下就要看最终 Maven 选择了哪个版本,以及旧版本是从哪个依赖传递进来的。


五、只查看某个依赖:-Dincludes

如果依赖树太长,可以用 -Dincludes 过滤。

例如只看 Jackson:

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:jackson-databind

只看 Guava:

mvn dependency:tree -Dincludes=com.google.guava:guava

只看 SLF4J:

mvn dependency:tree -Dincludes=org.slf4j

dependency:tree 支持 includesexcludes 参数,过滤格式为 [groupId]:[artifactId]:[type]:[version],各段都支持通配符。(Apache Maven)

常用命令:

mvn dependency:tree -Dincludes=org.slf4j
mvn dependency:tree -Dincludes=ch.qos.logback
mvn dependency:tree -Dincludes=com.fasterxml.jackson.core
mvn dependency:tree -Dincludes=com.google.guava
mvn dependency:tree -Dincludes=io.netty

六、输出到文件方便搜索

项目依赖多时,控制台不好看,可以输出到文件:

mvn dependency:tree -DoutputFile=dependency-tree.txt

官方文档说明,dependency:tree 支持通过 outputFile 将依赖树输出到文件,也支持 text、dot、graphml、tgf、json 等输出格式。(Apache Maven)

例如输出 JSON:

mvn dependency:tree -DoutputType=json -DoutputFile=dependency-tree.json

输出后可以搜索:

jackson
guava
netty
slf4j
logback
tomcat
hibernate

七、看 omitted 信息

可以加:

mvn dependency:tree -Dverbose

它会显示一些被 Maven 省略的依赖节点,例如:

omitted for conflict with 2.17.2
omitted for duplicate

这对判断版本冲突很有帮助。

注意:不同 Maven Dependency Plugin 版本的输出细节可能不同。如果 -Dverbose 输出不明显,可以结合 -Dincludes 或输出文件搜索。


八、Maven为什么会选这个版本?

举一个例子。

依赖关系:

demo
├── A
│   └── C:1.0
└── B
    └── D
        └── C:2.0

这里 C:1.0 离 demo 更近,所以 Maven 可能选择 C:1.0

再比如:

demo
├── A
│   └── C:1.0
└── B
    └── C:2.0

如果两个版本深度相同,则先声明的依赖路径优先。Maven 官方文档将这种规则称为 dependency mediation,也就是通过“最近定义”和“同深度先声明优先”来决定最终版本。(Apache Maven)

所以排查冲突时,要看:

冲突依赖有几个版本
每个版本从哪条路径进来
哪个版本最终生效
最终生效版本是否符合项目预期

九、解决方式一:直接声明需要的依赖版本

如果你明确知道项目应该使用某个版本,可以在当前项目中直接声明它。

例如统一使用 Guava 32.1.3:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

因为它变成了当前项目的直接依赖,路径更近,通常可以覆盖传递依赖中的旧版本。

适合场景:

你确实直接使用了这个依赖
你明确知道应该使用哪个版本
该版本与其他依赖兼容

不适合:

你只是为了压住冲突,随便加一个版本
项目根本不直接使用该依赖
该版本可能破坏其他库兼容性

十、解决方式二:用 dependencyManagement 统一版本

多模块项目更推荐使用 dependencyManagement 统一版本。

父 POM 示例:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子模块中可以不写版本:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

Maven 官方文档说明,dependencyManagement 是集中管理依赖信息的机制,尤其适合多个项目或子模块继承同一个父 POM 的场景。(Apache Maven)

注意:

dependencyManagement 不等于真正引入依赖
它只是管理版本
真正引入还要写在 dependencies 里

十一、解决方式三:使用BOM统一依赖版本

Spring Boot 项目常见做法是使用 Spring Boot BOM。

如果使用:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.5.15</version>
</parent>

Spring Boot 会帮你管理一批常用依赖版本。

如果不使用 parent,也可以导入 BOM:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.5.15</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后依赖可以不写版本:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot 项目不建议随便覆盖 Jackson、Tomcat、Logback、Hibernate、Spring Framework 等核心依赖版本。除非你明确知道为什么要覆盖,以及覆盖后对整个依赖树的影响。


十二、解决方式四:使用 exclusions 排除传递依赖

如果某个依赖传递进来了不需要的旧 Jar,可以用 exclusions 排除。

例如某个 SDK 带进旧版 Guava:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>some-sdk</artifactId>
    <version>1.0.0</version>
</dependency>

查看依赖树:

mvn dependency:tree -Dincludes=com.google.guava:guava

发现:

com.example:some-sdk:jar:1.0.0
\- com.google.guava:guava:jar:18.0

可以这样排除:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>some-sdk</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>

然后自己声明需要的版本:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

Maven 官方文档说明,exclusions 是定义在某个具体 dependency 里的,用于排除由该依赖路径传递进来的特定 groupId 和 artifactId;官方也提醒,exclusion 更像最后手段,应该确认到底是哪条依赖路径引入了不想要的传递依赖。(Apache Maven)


十三、不要滥用 exclusions

exclusions 很有用,但不能乱用。

不建议这样:

看到冲突就排除
不知道谁需要这个依赖也排除
把一堆依赖全部排掉
复制网上的 exclusions 不理解原因

排除依赖前要确认:

1. 这个依赖是谁带进来的
2. 项目是否真的不需要它
3. 排除后有没有替代版本
4. 排除后是否影响原依赖的功能
5. 测试是否覆盖相关功能

错误排除可能导致:

ClassNotFoundException
NoClassDefFoundError
某些功能运行到一半才报错

十四、解决方式五:升级上游依赖

有些冲突最好不要靠排除解决,而是升级上游依赖。

例如:

old-sdk 1.0 -> guava 18.0
old-sdk 2.0 -> guava 32.x

如果可以升级 old-sdk,优先升级它,而不是强行排除里面的传递依赖。

适合升级上游依赖的场景:

上游依赖已有兼容新版本
旧版本存在安全漏洞
旧版本不支持当前 JDK
旧版本与 Spring Boot 3 / 4 不兼容

升级后仍要执行:

mvn dependency:tree
mvn clean test
mvn clean package

十五、解决方式六:排查 scope 是否写错

Maven 的 scope 也会导致运行时依赖缺失。

常见 scope:

scope含义常见问题
compile默认,编译和运行都需要最常用
provided编译需要,运行由容器提供打包后可能没有
runtime编译不需要,运行需要数据库驱动常见
test只测试使用主程序运行时没有

典型错误:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
    <scope>test</scope>
</dependency>

这样正式运行时可能找不到数据库驱动。

如果你用 Spring Boot 打 fat jar,大多数业务依赖不应该随便写成 provided


十六、解决方式七:排查重复日志依赖

日志依赖冲突很常见。

典型现象:

SLF4J: Class path contains multiple SLF4J bindings
LoggerFactory is not a Logback LoggerContext
NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder

常见冲突:

slf4j-log4j12
log4j-to-slf4j
log4j-slf4j-impl
logback-classic
jul-to-slf4j

先看依赖树:

mvn dependency:tree -Dincludes=org.slf4j
mvn dependency:tree -Dincludes=ch.qos.logback
mvn dependency:tree -Dincludes=org.apache.logging.log4j

Spring Boot 默认日志体系通常是:

spring-boot-starter-logging
logback-classic
slf4j

如果你没有明确切换 Log4j2,不建议乱加日志实现依赖。


十七、解决方式八:排查 Jackson 版本冲突

Spring Boot 项目中 Jackson 冲突也很常见。

典型报错:

NoSuchMethodError: com.fasterxml.jackson.databind.ObjectMapper.xxx
ClassNotFoundException: com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
InvalidDefinitionException

排查:

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core
mvn dependency:tree -Dincludes=com.fasterxml.jackson.datatype
mvn dependency:tree -Dincludes=com.fasterxml.jackson.module

Spring Boot 项目优先使用 Spring Boot 管理的 Jackson 版本,不建议手动指定:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>某个随手写的版本</version>
</dependency>

除非有明确安全修复或兼容要求,并且完整测试过。


十八、解决方式九:排查 Netty 版本冲突

使用这些技术时,Netty 冲突很常见:

Spring WebFlux
Reactor Netty
Redisson
Dubbo
Elasticsearch Client
gRPC
RocketMQ
Netty自定义通信

排查:

mvn dependency:tree -Dincludes=io.netty

常见问题:

NoSuchMethodError
ClassNotFoundException
Native transport 加载失败
不同组件依赖不同 Netty 小版本

处理方式:

优先让框架 BOM 管理版本
不要手动混用多个 Netty 版本
升级上游组件
必要时用 dependencyManagement 统一版本

十九、解决方式十:用 effective-pom 看最终POM

有时候你看当前 pom.xml 看不出问题,因为版本来自:

父POM
dependencyManagement
Spring Boot BOM
公司父工程
profile

可以执行:

mvn help:effective-pom

输出到文件:

mvn help:effective-pom -Doutput=effective-pom.xml

然后搜索:

dependencyManagement
jackson
guava
netty
slf4j
spring-boot-dependencies

effective-pom 能帮你看到 Maven 合并父 POM、profiles、dependencyManagement 后的最终 POM。


二十、用 dependency:analyze 找未声明和未使用依赖

可以执行:

mvn dependency:analyze

Maven Dependency Plugin 官方文档说明,dependency:analyze 会进行字节码分析,用于发现缺失依赖和未使用依赖;dependency:analyze-dep-mgt 则可以检查最终解析依赖与 dependencyManagement 中配置之间的不匹配。(Apache Maven)

常见输出可能包括:

Used undeclared dependencies
Unused declared dependencies

含义:

Used undeclared dependencies:
代码里用了这个依赖,但 pom.xml 没直接声明,可能是靠传递依赖带进来的

Unused declared dependencies:
pom.xml 声明了依赖,但代码没有直接使用

不要机械删除所有 “Unused declared dependencies”,因为有些依赖可能是运行时、反射、SPI、注解处理或框架自动加载用到的。


二十一、Spring Boot项目的推荐处理方式

Spring Boot 项目优先遵守这个顺序:

1. 使用 spring-boot-starter-parent 或 spring-boot-dependencies BOM
2. 不随便写 Spring Boot 已管理依赖的 version
3. 用 dependency:tree 找冲突来源
4. 优先升级第三方 Starter
5. 必要时用 exclusions 排除明确不需要的传递依赖
6. 最后才用 dependencyManagement 覆盖核心依赖版本

不推荐:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>随便指定一个版本</version>
</dependency>

Spring Boot 项目中,Spring Framework、Jackson、Tomcat、Logback、Hibernate 等核心版本应该尽量由 Spring Boot 管理。


二十二、多模块项目怎么统一依赖?

多模块项目建议在父 POM 中统一管理版本。

父 POM:

<properties>
    <jackson.version>2.19.2</jackson.version>
    <guava.version>32.1.3-jre</guava.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>${guava.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子模块:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

这样可以避免每个子模块各写各的版本。


二十三、常见案例:Guava版本冲突

报错

java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument

排查

mvn dependency:tree -Dincludes=com.google.guava:guava

可能看到:

com.example:demo
+- com.example:old-sdk:1.0
|  \- com.google.guava:guava:18.0
\- com.example:new-sdk:2.0
   \- com.google.guava:guava:32.1.3-jre

解决思路

如果项目需要新版 Guava:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>
    </dependencies>
</dependencyManagement>

如果旧 SDK 带入的 Guava 完全不需要,也可以排除:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>old-sdk</artifactId>
    <version>1.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>

二十四、常见案例:Jackson版本冲突

报错

java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ObjectMapper.xxx

排查

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core

可能原因

手动指定了 jackson-databind 旧版本
某个 SDK 带入旧版 Jackson
Spring Boot 管理的版本被覆盖
不同 Jackson 模块版本不一致

解决建议

Spring Boot 项目优先删除手写 Jackson version
让 Spring Boot BOM 管理 Jackson
如果确实要升级,尽量整组统一 jackson-core、jackson-databind、jackson-annotations、jackson-datatype-jsr310

二十五、常见案例:日志依赖冲突

报错

SLF4J: Class path contains multiple SLF4J bindings

排查

mvn dependency:tree -Dincludes=org.slf4j
mvn dependency:tree -Dincludes=ch.qos.logback
mvn dependency:tree -Dincludes=org.apache.logging.log4j

解决思路

确认项目使用 Logback 还是 Log4j2
不要同时引入多个日志实现
Spring Boot 默认使用 Logback
如果切换 Log4j2,要按 Spring Boot 推荐方式排除默认 logging starter

二十六、完整排查清单

遇到 Maven 依赖冲突,按下面步骤来:

1. 保存完整报错,不要只看第一行
2. 判断是 NoSuchMethodError、ClassNotFoundException 还是 NoClassDefFoundError
3. 找到报错中的类名或包名
4. 判断它属于哪个依赖
5. 执行 mvn dependency:tree
6. 使用 -Dincludes 过滤目标依赖
7. 查看是否存在多个版本
8. 找到冲突依赖的引入路径
9. 判断 Maven 最终选择的版本
10. 优先使用 BOM 或 dependencyManagement 统一版本
11. 必要时使用 exclusions 排除旧版本
12. 检查 scope 是否错误
13. 执行 mvn help:effective-pom 查看最终版本
14. 执行 mvn dependency:analyze 辅助检查
15. 执行 mvn clean test / mvn clean package 验证
16. 在和生产一致的环境中运行验证

二十七、常用命令汇总

# 查看完整依赖树
mvn dependency:tree

# 查看某个依赖
mvn dependency:tree -Dincludes=com.google.guava:guava

# 查看某个 groupId 下所有依赖
mvn dependency:tree -Dincludes=com.fasterxml.jackson.core

# 输出到文件
mvn dependency:tree -DoutputFile=dependency-tree.txt

# 输出 JSON
mvn dependency:tree -DoutputType=json -DoutputFile=dependency-tree.json

# 查看最终 POM
mvn help:effective-pom

# 输出最终 POM 到文件
mvn help:effective-pom -Doutput=effective-pom.xml

# 分析未声明和未使用依赖
mvn dependency:analyze

# 检查 dependencyManagement 与最终解析结果
mvn dependency:analyze-dep-mgt

# 清理并测试
mvn clean test

# 清理并打包
mvn clean package

二十八、常见问题FAQ

1. Maven依赖冲突一定要用 exclusions 吗?

不一定。优先考虑:

升级上游依赖
使用 BOM
用 dependencyManagement 统一版本
直接声明需要的依赖版本

exclusions 应该在明确知道哪条路径引入了不需要的依赖后再使用。


2. dependencyManagement 会自动引入依赖吗?

不会。

dependencyManagement 只管理版本,不会自动把依赖加入项目。真正引入依赖仍然要写在 <dependencies> 里。


3. 为什么我明明写了版本,Maven还是用了别的版本?

可能是:

父POM或BOM管理了版本
dependencyManagement覆盖了版本
多模块父子POM继承导致最终版本变化
profile影响了依赖

执行:

mvn help:effective-pom

查看最终 POM。


4. NoSuchMethodError一定是依赖冲突吗?

大概率和版本不匹配有关,但不一定只来自 Maven。

也可能是:

服务器旧 Jar 没清理
容器自带依赖冲突
IDEA 和打包运行 classpath 不一致
插件或 ClassLoader 隔离问题

先用 dependency:tree 排查项目依赖,再检查运行环境。


5. Spring Boot项目能不能手动指定Jackson版本?

可以,但不建议随便指定。

Spring Boot 已经管理了一组兼容版本。除非有安全漏洞修复或明确兼容需求,否则优先使用 Boot 管理的版本。


6. IDEA里怎么查看Maven依赖冲突?

可以在 Maven 工具窗口查看依赖树,也可以使用依赖图功能。但最终仍建议用命令:

mvn dependency:tree

命令行结果更适合复制、搜索、记录和排查。


7. 删除 .m2 仓库能解决依赖冲突吗?

通常不能。

删除 .m2 主要解决本地缓存损坏或下载失败,不解决版本选择和传递依赖冲突。

依赖冲突要看:

dependency:tree
dependencyManagement
exclusions
BOM
scope

二十九、最终总结

Maven 依赖冲突排查的核心不是“猜”,而是看清楚依赖树。

记住这几个规则:

Maven会自动引入传递依赖
多个版本冲突时,Maven会按依赖调解规则选择最终版本
dependency:tree可以看到依赖来源
dependencyManagement用于统一版本
exclusions用于排除特定传递依赖
Spring Boot项目优先使用官方BOM管理版本
不要滥用exclusions
不要随便覆盖核心依赖版本

推荐排查命令:

mvn dependency:tree
mvn dependency:tree -Dincludes=目标groupId:artifactId
mvn help:effective-pom
mvn dependency:analyze

只要能回答这三个问题,依赖冲突基本就能解决一大半:

最终生效的是哪个版本?
这个版本是从哪条依赖路径来的?
我应该统一版本、升级上游依赖,还是排除传递依赖?

三十、相关文章

Maven 依赖下载失败可以看:

Maven Could not transfer artifact 下载失败解决:settings.xml、国内镜像、本地缓存与代理排查

Maven 国内镜像配置可以看:

Maven国内镜像settings.xml配置大全:阿里云、腾讯云、华为云、清华源

Maven 编译器错误可以看:

No compiler is provided in this environment解决办法

JDK 下载地址可以看:

各版本JDK镜像下载地址:JDK8 / 11 / 17 / 21 / 25 / 26

Spring Boot 与 JDK 兼容可以看:

Spring Boot与JDK版本兼容表

完整 Java 环境配置专题:

Java开发环境配置专题


更新记录

2026-07-10:
- 创建 Maven 依赖冲突排查教程
- 增加 dependency:tree 使用方法
- 增加 includes / outputFile / outputType 示例
- 增加 dependencyManagement、BOM、exclusions 处理方式
- 增加 Guava、Jackson、日志、Netty 常见冲突案例
- 增加 effective-pom、dependency:analyze 排查命令
- 增加 Spring Boot 项目依赖版本建议