Maven依赖冲突源于不同路径引入同一坐标的不同版本,其调解机制按“最近优先”和“声明顺序”选版本;可通过<exclusions>排除特定传递依赖,或用<dependencyManagement>统一锁定版本,并借助mvn dependency:tree命令验证结果。

Maven 处理依赖冲突的核心是依赖调解机制,它按“最近优先”和“声明顺序”自动选择版本;但当自动结果不符合预期时,就需要手动干预——常用手段包括用 <exclusions> 排除不需要的传递依赖,或用 <dependencyManagement> 统一锁定版本。
理解 Maven 的依赖冲突是怎么产生的
项目直接声明的依赖会拉入其自身的依赖(即传递依赖),不同路径可能引入同一坐标但不同版本的 jar。例如 A → B → C-1.0,同时 A → D → C-2.0,这时 C 就出现版本冲突。Maven 默认保留离项目路径更近、或在 pom 中声明更靠前的那个版本,但这个结果未必是你想要的。
用 <exclusions> 精准排除特定传递依赖
<exclusions> 写在某个 <dependency> 内部,作用是阻止该依赖带入指定的子依赖,不改变它自身的行为。写法必须包含 <groupId> 和 <artifactId>:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
- 排除后,spring-boot-starter-web 不再带入嵌入式 Tomcat,适合部署到外部容器场景
-
<exclusion>中的 groupId/artifactId 必须与实际传递依赖完全一致,大小写、拼写都不能错 - 一个
<dependency>可含多个<exclusion>,用于一次性切断多个干扰项
比 exclusions 更推荐的全局控制方式:dependencyManagement
当多个模块都用到相同依赖(如 logback、jackson),靠逐个 <exclusions> 容易遗漏且难维护。此时应在父 pom 的 <dependencyManagement> 中统一声明版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
</dependencyManagement>
- 子模块只需声明 groupId 和 artifactId,无需 version,Maven 自动采用 management 中定义的版本
- 它能覆盖传递依赖的版本,比 exclusions 更彻底、更可维护
- 配合
<scope>import</scope>还可导入 Spring Boot 或 Alibaba BOM,实现整套技术栈版本对齐
验证和调试依赖树的实用命令
执行以下命令可看清实际解析出的依赖结构,确认冲突是否解决、exclusion 是否生效:
-
mvn dependency:tree -Dverbose:显示全部依赖,含被忽略(omitted for duplicate)的项 -
mvn dependency:tree -Dincludes=commons-lang3:只查指定坐标,快速定位来源 -
mvn dependency:tree -Dexcludes=junit:过滤掉某些干扰项,让输出更清晰


















