依赖冲突产生的原因:

  1. 如果项目的依赖A和依赖B同时引入了依赖C。
  2. 如果依赖C在A和B中的版本不一致就可能依赖冲突。
  3. 比如 项目 <- A, B, A <- C(​​1.0​​),B <- C(​​1.1​​)。
  4. 那么maven如果选择高版本C(​​1.1​​)来导入(这个选择maven会根据不等路径短路径原则和同等路径第一声明原则选取),C(​​1.0​​)中的类c在C(​​1.1​​)中被修改而不存在了。
  5. 在编译期可能并不会报错,因为编译的目的只是把业务源代码编译成class文件,所以如果项目源代码中没有引入共有依赖C因升级而缺失的类c,就不会出现编译失败。除非源代码就引入了共有依赖C因升级而缺失的类c则会直接编译失败。
  6. 在运行期,很有可能出现依赖A在执行过程中调用C(​​1.0​​)以前有但是升级到C(​​1.1​​)就缺失的类c,导致运行期失败,出现很典型的依赖冲突时的​​NoClassDefFoundError​​错误。
  7. 如果是升级后出现原有的方法被修改而不存在的情况时,就会抛出​​NoSuchMethodError​​错误。

传递依赖

maven坐标有一项scope此元素指的是任务的类路径(编译和运行时,测试等)以及如何限制依赖关系的传递性。

有 6 种可用的限定范围:

          compile 编译依赖范围 如果没有指定 scope 标签,maven 默认为这个范围。

test 测试依赖范围 正常使用应用程序不需要依赖关系 Junit

provided 已提供依赖范围 它只适用于编译和测试 servlet-api

runtime 运行时依赖范围 此范围表示编译不需要依赖关系,而是用于执行 jdbc驱动

system和 provided 依赖范围一致,需要通过 <systemPath> 显示指定,且可以引用环境变量

import 导入依赖范围。使用该选项,通常需要 <type>pom</type>,将目标 pom 的 dependencyManagement 配置导入合并到当前 pom 的  dependencyManagement 元素。

maven解决冲突以及常用命令_传递性

依赖传递性以及依赖范围

何为传递性依赖

maven解决冲突以及常用命令_传递性_02

依赖范围与传递性依赖的关系

maven解决冲突以及常用命令_maven_03

依赖冲突解决方案

1、maven本身处理机制-依赖调解

短路径优先:假如有以下依赖:A -> B -> C ->X(版本 1.0) 和 A -> D -> X(版本 2.0),则优先解析较短路径的 X(版本 2.0);

先声明优先:若路径长度相同,则谁先声明,谁被解析。

2、可选依赖

optional可选依赖

A->B、B->X(可选),B->Y(可选) X,Y依赖不会传递到A中

可选依赖用于两个特性相互互斥,例如 mysql,PostgreSQL不能同时实现特性

3、排除依赖

exclusions元素声明排除依赖

4、归类依赖-版本锁定

利用properties统一声明版本,涉及到相同系列包,修改${properties}即可统一替换

优化依赖

1、查看已解析的依赖

mvn dependency:list

一层为顶层依赖,顶层依赖的依赖为二级依赖,以此类推

maven解决冲突以及常用命令_依赖关系_04

2、查看依赖树

mvn dependency:tree

通过上方的命令解析之后会构成依赖树,利用依赖树可以清楚看到依赖引入的传递路径

maven解决冲突以及常用命令_传递性_05

3、分析项目当前依赖

mvn dependency:analyze

Used undeclared dependencies found

这个是指某些依赖的包在代码中有用到它的代码,但是它并不是直接的依赖(就是说没有在pom中直接声明),是通过引入传递下来的包

Unused declared dependencies found

这个是指我们在pom中声明了依赖,但是在实际代码中并没有用到这个包!也就是多余的包。 这个时候我们就可以把这个依赖从pom中剔除

注意:这里说的实际代码没有用到,指的是在main/java和test里没有用的,但是并不是意味着真的没有用到这些包,有可能配置文件中引用或者其他扩展点自动加载这些包,所以我们在删除依赖的时候一定要小心,做好备份,因为这类引用maven是分析不出来的。

常用命令

修改版本号命令

安装插件

maven解决冲突以及常用命令_maven_06

mvn vsersion:set -DnewVersion=1.1-SANPSHOT

激活环境

mvn clean package -P dev

跳过单元测试

-Dmaven.test.skip=true