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 Helper插件的使用

配置Maven Helper插件

因为在准备讲Maven用Maven Helper插件的时候,在网上学习,发现资料很少,我就把自己研究的配置分享给大家!!IDEA(本人用的2017.2版本)

IDEA设置:已打开软件:File--> Setting-->Plugins

未打开IDEA内:Configure --> Project Defaults --> Settings-->Plugins

如果下载失败弹出一个红色提示,说加载时间过长,下载不下来jar文件,本人提供了一个jar文件

链接:https://pan.baidu.com/s/1wz40Sbmxo-BT-kLCVUnezQ

密码:0lkq

本人在百度云盘分享的jar文件,下图有操作,把这个此jar文件添加到IDEA里(MavenHelper插件)

这个时候达到我这个图就可以了,应用以后会重启软件,这时候我们需要Maven项目的POM.xml

如果报红就去检查Maven Helper是否启动,重新启动程序!一直到第4步出现!Text可以添加依赖的xml;  Dependency Analyzer 可以使用Maven Helper,就是打开该pom文件的Dependency Analyzer视图(在文件打开之后,文件下面会多出这样一个tab),进入Dependency Analyzer视图之后有三个查看选项,分别是Conflicts(冲突)、All Dependencies as List(列表形式查看所有依赖)、All Dependencies as Tree(树结构查看所有依赖)。并且这个页面还支持搜索。很方便!并且使用该插件还能快速的执行maven命令。如下图:

安装的过程可能会出现下面的报错,是因为插件和idea的版本不兼容,换个插件版本就好了。

转载请注明出处。 https://blog.csdn.net/qq_33541575/article/details/80211122

maven中jar冲突解决的更多相关文章

  1. Maven中 jar包冲突原理与解决办法

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

  2. Eclipse中Egit冲突解决

    Eclipse中Egit冲突解决 Git 作为进来最流行的分布式版本控制软件来说应用的十分广泛.EGit就是一款Eclipse上的Git插件.在使用Egit提交项目时,有时会产生冲突,需要对代码进行m ...

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

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

  4. Maven 传递依赖冲突解决(了解)

    1 传递依赖冲突解决(了解) 传递依赖:A(项目)依赖B,B依赖C(1.1版本),B是A的直接依赖,C就是A的传递依赖 导入依赖D,D依赖C(1.2版本) 1.1 Maven自己调解原则 1.1.1  ...

  5. 加快maven中jar包的下载速度,maven镜像收集

    maven下载jar包的默认仓库是http://my.repository.com/repo/path速度较慢,通过配置国内镜像提高下载速度 1.打开eclipse--->Window---&g ...

  6. .Net中DLL冲突解决(真假美猴王)

    <西游记>中真假美猴王让人着实难以区分,但是我们熟知了其中的细节也不难把他们剥去表象分别出来.对问题不太关心的可以直接调到文中关于.Net文件版本的介绍 问题 最近在编译AKKA.net ...

  7. 加快maven中jar包的下载速度

    maven下载jar包的默认仓库是http://my.repository.com/repo/path速度较慢,通过配置国内镜像提高下载速度 1.打开eclipse--->Window---&g ...

  8. 团队开发中Git冲突解决

    正常来说我们团队协作开发过程中,冲突是常有的事,下面介绍下本人在开发中的解决办法. 冲突的主要原因就是由于我们开发人员在分支的同一位置写入了不一样的代码,然后合并到主干上导致我们冲突. 方法: 当冲突 ...

  9. git在idea中的冲突解决(非常重要)

    1.什么是冲突 冲突是指当你在提交或者更新代码时被合并的文件与当前文件不一致.读起来有点绕,结合下面的案例理解. 从上面对冲突的定义来看,冲突时发生在同一个文件上的. 2.生产上冲突的场景 常见冲突的 ...

随机推荐

  1. 020 文件(图片)上传功能---涉及switchhost和Nginx的使用

    文件的上传并不只是在品牌管理中有需求,以后的其它服务也可能需要,因此我们创建一个独立的微服务,专门处理各种上传. 1.搭建模块 (1)创建模块 (2)依赖 我们需要EurekaClient和web依赖 ...

  2. Sitecore 8.2 防火墙规则的权威指南

    如今,使用多层安全保护您的数据不再是奢侈品; 这是不容谈判的.此外,您需要确保Sitecore解决方案保持运行并与集成服务(例如SQL,Mongo,Solr)通信,同时保持相同的安全级别. 让我们假设 ...

  3. springboot处理date参数

    前言 最近在后台开发中遇到了时间参数的坑,就单独把这个问题提出来找时间整理了一下: 正文 测试方法 bean代码: public class DateModelNoAnnotation { priva ...

  4. Matlab分布云图绘制(渐变彩色)

    方法1. 函数:fill 举例说明:应力分布云图 x=[0 1 1 0 0]; %x坐标 y=[0 0 1 1 0]; %y坐标 stress=[1 2 3 4 1] %应力大小 fill(x,y,s ...

  5. sqlserver读取日志以及复制

    首选,在事务日志中,到底有多少是需要复制的?使用以下命令,可以确定事务日志中被标志为复制的命令有多少. USE test GO SELECT count(*) FROM ::fn_dblog(NULL ...

  6. 在 Docker 中运行 SpringBoot 应用

    创建 SpringBoot 项目 用 Idea 创建一个 SpringBoot 项目,编写一个接口: package cloud.dockerdemo import org.springframewo ...

  7. 前端开发常用 JS 方法

    1,获取文件本地url,在上传之前预览 /** * 获取图片嗯滴url,在上传之前预览 * @param file 选择的图片文件 * @returns {*} url */ getFileLocat ...

  8. 重温拉格朗日乘子法和KKT条件

    在求取有约束条件的优化问题时,拉格朗日乘子法(Lagrange Multiplier) 和KKT条件是非常重要的两个求取方法,对于等式约束的优化问题,可以应用拉格朗日乘子法去求取最优值:如果含有不等式 ...

  9. Mybatis 原理分析

    对于入门程序的流程分析 使用过程 读配置文件 读取配置文件时绝对路径和相对路径(web工程部署后没有src路径)都有一定问题,实际开发中一般有两种方法 使用类加载器,它只能读取类路径的配置文件 使用S ...

  10. 查看mysql字符集、修改数据库、数据表、字段字符集

    查看所有表的字符集 SELECT table_name, table_type, engine, version, table_collation FROM information_schema.ta ...