Maven中jar包冲突是开发过程中比较常见而又令人头疼的问题,我们需要知道 jar包冲突的原理,才能更好的去解决jar包冲突的问题。本文将从jar包冲突的原理和解决两个方面阐述Maven中jar包冲突的解决办法。

一、Maven中jar包冲突产生原因
MAVEN项目运行中如果报如下错误:

Caused by:java.lang.NoSuchMethodError
Caused by: java.lang.ClassNotFoundException

十有八九是Maven jar包冲突造成的。那么jar包冲突是如何产生的?

首先我们需要了解jar包依赖的传递性。

1、依赖传递
当我们需要A的依赖的时候,就会在pom.xml中引入A的jar包;而引入的A的jar包中可能又依赖B的jar包,这样Maven在解析pom.xml的时候,会依次将A、B 的jar包全部都引入进来。

举个例子:
在Spring Boot应用中导入Hystrix和原生Guava的jar包:

<!--原生Guava API-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>

<!--hystrix依赖(包含对Guava的依赖)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>

利用Maven Helper插件得到项目导入的jar包依赖树:

从图中可以看出Hystrix包含对Guava jar包依赖的引用: Hystrix -> Guava,所以在引入Hystrix的依赖的时候,会将Guava的依赖也引入进来。

2、jar包冲突原理
那么jar包是如何产生冲突的?
假设有如下依赖关系:

A->B->C->D1(log 15.0):A中包含对B的依赖,B中包含对C的依赖,C中包含对D1的依赖,假设是D1是日志jar包,version为15.0

E->F->D2(log 16.0):E中包含对F的依赖,F包含对D2的依赖,假设是D2是同一个日志jar包,version为16.0

当pom.xml文件中引入A、E两个依赖后,根据Maven传递依赖的原则,D1、D2都会被引入,而D1、D2是同一个依赖D的不同版本。
当我们在调用D2中的method1()方法,而D1中是15.0版本(method1可能是D升级后增加的方法),可能没有这个方法,这样JVM在加载A中D1依赖的时候,找不到method1方法,就会报NoSuchMethodError的错误,此时就产生了jar包冲突。

注:
如果在调用method2()方法的时候,D1、D2都含有这个方法(且升级的版本D2没有改动这个方法,这样即使D有多个版本,也不会产生版本冲突的问题。)

举个例子:

利用Maven Helper插件分析得出:Guava这个依赖包产生冲突。
我们之前导入了Guava的原生jar包,版本号是20.0;而现在提示Guava产生冲突,且冲突发生位置是Hystrix所在的jar包,所以可以猜测Hystrix中包含了对Guava不同版本的jar包的引用。

为了验证我们的猜想,使用Maven Helper插件打印出Hystrix依赖的jar tree:

可以看到:Hystrix jar中所依赖的Guava jar包是15.0版本的,而我们之前在pom.xml中引入的原生Guava jar包是20.0版本的,这样Guava就有15.0 与20.0这两个版本,因此发生了jar包冲突。

二、 Maven中jar包冲突的解决方案
Maven 解析 pom.xml 文件时,同一个 jar 包只会保留一个,那么面对多个版本的jar包,需要怎么解决呢?

1、 Maven默认处理策略
最短路径优先

Maven 面对 D1 和 D2 时,会默认选择最短路径的那个 jar 包,即 D2。E->F->D2 比 A->B->C->D1 路径短 1。

最先声明优先

如果路径一样的话,如: A->B->C1, E->F->C2 ,两个依赖路径长度都是 2,那么就选择最先声明。

2、移除依赖:用于排除某项依赖的依赖jar包
(1)我们可以借助Maven Helper插件中的Dependency Analyzer分析冲突的jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去。

再刷新以后冲突就会消失。

(2)手动排除
或者手动在pom.xml中使用<exclusion>标签去排除冲突的jar包(上面利用插件Maven Helper中的execlude方法其实等同于该方法):

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>

mvn分析包冲突命令:

mvn dependency:tree

3 版本锁定原则:一般用在继承项目的父项目中
正常项目都是多模块的项目,如moduleA和moduleB共同依赖X这个依赖的话,那么可以将X抽取出来,同时设置其版本号,这样X依赖在升级的时候,不需要分别对moduleA和moduleB模块中的依赖X进行升级,避免太多地方(moduleC、moduleD….)引用X依赖的时候忘记升级造成jar包冲突,这也是实际项目开发中比较常见的方法。

首先定义一个父pom.xml,将公共依赖放在该pom.xml中进行声明:

<properties>
<spring.version>spring4.2.4</spring.version>
<properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.versio}</version>
</dependency>
</dependencies>
</dependencyManagement>

这样如moduleA和moduleB在引用Spring-beans jar包的时候,直接使用父pom.xml中定义的公共依赖就可以:
moduleA在其pom.xml使用spring-bean的jar包(不用再定义版本):

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
</dependencies>
moduleB在其pom.xml使用spring-bean的jar包如上类似:

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
</dependencies>

以上就是日常开发中解决Maven冲突的几个小方案,当然实际开发中jar包冲突的问题可能远远比这个更复杂,需要具体问题具体处理。

Maven中 jar包冲突原理与解决办法的更多相关文章

  1. Maven中jar包冲突的解决方式

    现象 创建一个maven工程,引入spring-context包. <dependency> <groupId>org.springframework</groupId& ...

  2. Maven中Jar包冲突,不让某个Jar包打入到工程中

     查看工程目前冲突的Jar包,这里以fastjson.jar为例: 打开工程的pom.xml,进入到Dependency Hierarchy页面搜寻目标Jar. 从这里我们可以看到目前工程中有2处导入 ...

  3. (转)maven下载jar包速度慢(解决办法)

    本文转载至http://blog.csdn.net/ko289830707/article/details/53559052 现在maven项目非常流行,因为它对jar实行了一个非常方便的管理,我们可 ...

  4. 【Maven】【IDEA】在idea中开发web项目,解决maven的jar包冲突的方法

    在idea中开发web项目,解决maven的jar包冲突的方法 第一步: 先对项目进行 clean ,再进行install 第二步: 出现NoSuchMethodException,ClassNotF ...

  5. SpringBoot读取war包jar包Resource资源文件解决办法

    SpringBoot读取war包jar包Resource资源文件解决办法 场景描述 在开发过程中我们经常会碰到要在代码中获取资源文件的情况,而我在最近在SpringBoot项目中时碰到一个问题,就是在 ...

  6. 【maven】排除maven中jar包依赖的解决过程 例子:spring cloud启动zipkin,报错maven依赖jar包冲突 Class path contains multiple SLF4J bindings.

    一直对于maven中解决jar包依赖问题的解决方法纠结不清: 下面这个例子可以说明一个很简单的解决方法: 项目启动报错: Connected to the target VM, address: '1 ...

  7. 解决Maven依赖jar包冲突总结

    maven导入jar包中的一些概念:      直接依赖:项目中直接导入的jar包,就是该项目的直接依赖包.      传递依赖:项目中没有直接导入的jar包,可以通过项目直接依赖jar包传递到项目中 ...

  8. 解决Maven的jar包冲突问题

    1. 问题描述 控制台说:无法将 com.zpx.servlet.MyServlet 识别为 javax.servlet.Servlet 2. 问题原因 Maven的一个核心功能就是一键构建,所以Ma ...

  9. Maven项目-jar包冲突:MyServlet is not a Servlet解决方法

    异常显示:运行时jar包冲突异常 问题所在: jar包冲突,自己导入的jar包与tomcat中的jar包相同. 解决方法: 对(servlet,jsp)jar包设置作用域. 再次启动项目,问题已解决.

随机推荐

  1. bootm跳转到kernel的流程

    转自 https://blog.csdn.net/ooonebook/article/details/53495021 一.bootm说明 bootm这个命令用于启动一个操作系统映像.它会从映像文件的 ...

  2. destoon搜索伪静态失败解决办法

    今天给一个朋友调试DT6.0内核的站点,搜索中文出现http 403 forbidden,找了半天,很纳闷,最后一个一个查看源代码总算找到,在此分享给大家! 解决的方法: 1.找到include/sa ...

  3. woocommerce隐藏breadcrumb面包屑导航

    woocommerce已经集成比较完善的组件,当然也包含breadcrumb面包屑导航,但是我们如果调整一下breadcrumb的位置要如何操作呢?首先要先把woocommerce隐藏breadcru ...

  4. 宝塔https部署没成功的原因排查

    今天ytkah在迁移一个客户网站的时候出了点问题,网站从旧的服务器(windows)换到新的服务器(阿里云centos 7,已经安装了宝塔面板),网站之前有用comodo的ssl证书,因为快要过期了, ...

  5. 【oracle】处理锁表

    查询锁表 select object_name,machine,s.sid,s.serial# from v$locked_object l,dba_objects o ,v$session swhe ...

  6. mac Sublime Text 快捷键

    mac Sublime Text 快捷键 Tab: 光标后缩进 Shift+Tab: 反缩进 cmd+P: 打开文件切换面板 cmd+/: 行注释 cmd+R: 快速列出/跳转到某个函数 双击可选中光 ...

  7. SpringMVC拦截器与SpringBoot自定义拦截器

    首先我们先回顾一下传统拦截器的写法: 第一步创建一个类实现HandlerInterceptor接口,重写接口的方法. 第二步在XML中进行如下配置,就可以实现自定义拦截器了 SpringBoot实现自 ...

  8. Python爬虫爬取BT之家找电影资源

    一.写在前面 最近看新闻说圣城家园(SCG)倒了,之前BT天堂倒了,暴风影音也不行了,可以说看个电影越来越费力,国内大厂如企鹅和爱奇艺最近也出现一些幺蛾子,虽然目前版权意识虽然越来越强,但是很多资源在 ...

  9. Zuul之路由熔断

    Zuul作为Netflix组件,可以与Ribbon.Eureka.Hystrix等组件结合,实现负载均衡.熔断器的功能 Spring boot2X集成zuul与consul实现负载均衡和反向代理 当后 ...

  10. CentOS7 CPU 降频问题

    CentOS7 系统默认的 CPUPOWER 策略是 powersave 节能模式,Google 了非常多的资料,一直没有找到解决办法,现在分享一下. 执行: tuned-adm profile th ...