什么是Maven依赖冲突
我相信你在开发中一定碰到过下面这些情况,尤其是在变更maven
依赖后
- 代码编写完成,启动报错
java.lang.NoSuchMethodException
,但是你检查了一圈发现IDE正确识别到了有这个方法
- 代码编写完成,启动报错
java.lang.ClassNotFoundException
,同样,IDE编辑器爷识别到有这个类
- 再或者,启动不报错,运行时,当调用到某给方法或者类时,出现上面两种异常
以上三种情况,大多数原因都是依赖冲突导致的。
依赖冲突就是maven依赖中存在如下情况:
- 一个依赖同时存在多版本
- maven在打包时只会选取其中一个版本,遵循最短路径原则。
- 如果你的应用运行在某些其他“容器”里面,例如Spark等可能依赖会和“容器”本身本来就存在的依赖冲突。
所以,如果你运气好,maven取到的一个版本恰好能满足其他代码的依赖调用,那就不会报错。
但是大多数情况就是由于取到的版本不对出现依赖缺失报错问题。
如何解决依赖冲突
前面我们提到,一个依赖同时存在多版本导致冲突,那我们要解决的就是保证工程依赖中只保留一个唯一的依赖版本。
看个例子
modelA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>demo</artifactId> <groupId>top.oneyoung.maven-conflict-demo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>modelA</artifactId> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> </dependencies>
</project>
|
modelB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>demo</artifactId> <groupId>top.oneyoung.maven-conflict-demo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>modelB</artifactId> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> </dependencies>
</project>
|
modelC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>demo</artifactId> <groupId>top.oneyoung.maven-conflict-demo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>modelC</artifactId>
<dependencies> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelA</artifactId> </dependency> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelB</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
</project>
|
这里的关系是,modelA、modelB、modelC 都是demo的子模块,C依赖B和A。
B和C都引入了fastjson
依赖,但是他们的版本并不一致,这就产生冲突了。看图
两种解决方案
排除其中一个依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>demo</artifactId> <groupId>top.oneyoung.maven-conflict-demo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>modelC</artifactId>
<dependencies> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelA</artifactId> <exclusions> <exclusion> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelB</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project>
|
C依赖A的模块排除了fastjson
依赖,所以现在只存在B中依赖的fastjson
了。
这种方式一般适用于,引用别人的包,因为你改不了别人依赖的版本,只能进行手动排除,使用自己的版本。
统一版本
如果是你自己能控制引入的依赖,建议进行依赖统一,我们这里示例的A、B、C三个模块都有一个父模块,所以我我们可以将这种常用的依赖进行父模块管理,dependencyManagement
demo xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>pom</packaging> <modules> <module>modelA</module> <module>modelB</module> <module>modelC</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.5</version> <relativePath/> </parent> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>demo</description> <properties> <java.version>1.8</java.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelA</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>top.oneyoung.maven-conflict-demo</groupId> <artifactId>modelB</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> </dependencies> </dependencyManagement>
</project>
|
在进行父模块版本管理后,子模块再引用改依赖就不用指定版本了,默认使用依赖管理的版本。spring boot parent
就是如此的。
modelA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>demo</artifactId> <groupId>top.oneyoung.maven-conflict-demo</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>modelA</artifactId> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency> </dependencies>
</project>
|
工具推荐
如果你在使用IDEA
进行开发,不妨安装下这个插件 Maven Helper
点击安装:https://plugins.jetbrains.com/plugin/7179-maven-helper
这个插件可以很方便定位冲突。