Maven如何解决jar包冲突的问题?

ops/2024/10/20 18:59:59/

在使用Maven进行项目构建的应用中,如果在应用运行期发生了NoSuchMethodError、ClassNotFoundException等异常或者错误时,需要考虑Jar包冲突的问题。


如果在应用中,我们同时依赖了两个第三方的jar包A,B,而A,B中又都依赖了C包,但是依赖的C的版本不同,那么就可能发生jar包冲突,导致最终编译打包后,应用的classpath中只有一个C的jar包。


那么,因为maven有一定的Jar包依赖传递原则,所以有可能他最终选择的jar包并不是我们真正想用的,那这时候怎么办呢?就需要我们手动的进行依赖仲裁,通过人工干预的方式来保留我们需要的jar包。
 

扩展知识:

1.依赖传递

几乎所有的Jar包冲突都和依赖传递原则有关,所以我们先说Maven中的依赖传递原则,主要由以下两个默认的原则:

最短路径优先原则
假如引入了2个Jar包A和B,都传递依赖了Z这个Jar包:A ->X ->Y ->Z(2.5)
B ->X -> Z(2.0)
那其实最终生效的是Z(2.0)这个版本。因为他的路径更加短

最先声明优先原则
如果路径长短一样,优先选最先声明的那个。
A ->Z(3.0)
B -> Z(2.5)
这里A最先声明,所以传递过来的Z选择用3.0版本的

2.依赖树

在开发中,我们可以通过maven的依赖树来判断是否发生了jar包冲突,以及如何发生的冲突,只需要在maven项目中使用以下命令即可打印依赖树:

mvn dependency:tree

 打印出来的就是整个项目的jar包依赖的一个树形结构,我们找到发生了冲突的jar包就可以查看他的多种不同版本的依赖路径了。


在IDEA中,也可以使用maven helper插件来快速查看依赖树及冲突情况。

3.依赖仲裁

如果经过分析,项目中发生了依赖冲突,那么就需要我们进行仲裁解决,解决的手段有以下几种:

3.1排除依赖 

在pom文件中,我们可以在一个<dependency></dependency>标签内使用排除jar包的方式进行jar包排除。


如我们想排除X中对于Y的依赖

 这样,在项目中,就只会依赖X,而X依赖的Y的对应版本就会被排除了

3.2版本锁定

一般在我们开发的web项目中都会有多个Module,每一个module都会有很多外部依赖,而多种依赖可能都依赖了jar包Y,就涉及到了多个版本,如果用排除法的话,需要一个一个的进行exclusion,这样太麻烦了。


有一个一劳永逸的方法进行版本锁定。


大型项目一般都会有父级pom,你想指定哪个版本只需要在你项目的父POM中定义如下

 

这样对于Y的jar包的依赖就只会保留3.0这个版本了。

但是需要注意的是dependencyManagement标签只能做依赖仲裁管理使用,他并不会引入对Jar包的依赖,还需要你使用dependency进行jar包引入。 


http://www.ppmy.cn/ops/25423.html

相关文章

使用Vue实现返回到上一个页面的时候进行参数的传递

需求&#xff1a;点击按钮进入到下一个页面&#xff0c;在新的页面进行一系列操作&#xff0c;操作完成之后点击按钮会返回到上一个页面&#xff0c;返回的时候还要携带这个页面的一些数据。 实现方式&#xff1a;使用组件内守卫&#xff0c;在组件进入到上一个页面时使用路由…

深入理解C语言中的 extern`和 static

1. extern 关键字 定义和用途 extern 关键字用于声明一个变量或函数&#xff0c;表示其定义在另一个文件或本文件的其他位置。使用 extern 可以在多个文件之间共享全局变量或函数。 示例 假设有两个源文件&#xff1a;main.c 和 helper.c。 helper.c #include <stdio.…

react-mosaic-component-一个React库--窗格布局

import { Mosaic, MosaicWindow, MosaicZeroState } from "react-mosaic-component";从名为react-mosaic-component的npm包中引入三个组件&#xff1a;Mosaic&#xff0c;MosaicWindow和MosaicZeroState。 react-mosaic-component是一个React库&#xff0c;用于创建…

笨蛋学C++【C++基础第六弹】

C基础第六弹 C面向对象1.C类 & 对象1.1C类定义1.2C对象1.3访问数据成员1.4类成员函数1.5类访问修饰符公有public成员私有private成员受保护protected成员继承中的特点 1.6构造函数 & 析构函数类的构造函数带参数的构造函数使用初始化列表来初始化字段类的析构函数 1.7拷…

JAVA面试题分享---多线程与线程池

多线程 什么是线程?线程和进程的区别?&#xff08;了解&#xff09; 线程&#xff1a;是进程的一个实体&#xff0c;是 cpu 调度和分派的基本单位&#xff0c;是比进程更小的 可以独立运行的基本单位。 进程&#xff1a;具有一定独立功能的程序关于某个数据集合上的一次运…

Spring Boot的热部署工具“AND”Swagger测试工具

Spring Boot的热部署&Swagger测试页面的使用 热部署指的是在项目无需重启的情况下&#xff0c;只需要刷新页面&#xff0c;即可获得已经修改的样式或功能。要注意该工具一般用于开发环境&#xff0c;在生产环境中最好不要添加这个工具。 对于无需重启便可刷新这么方便的工…

手持LED弹幕,超炫特效,让你的每一次出场都耀眼夺目!

在这个快节奏的数字时代&#xff0c;沟通不再局限于言语和文字&#xff0c;就连表白、追星、晚会互动&#xff0c;甚至日常的提词都需要一点科技的火花来点燃气氛。于是&#xff0c;手持LED弹幕滚动屏&#xff0c;这个集实用与趣味于一身的神器&#xff0c;悄然成为了社交场上的…

Java23种设计模式-行为型模式之责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;:允许将多个对象连接成一条链&#xff0c;并沿着这条链传递一个请求&#xff0c;直到链上的某个对象能够处理该请求为止。这种模式的目的是解耦请求的发送者和接收者&#xff0c;同时允许多个对象有机会处理…