maven依赖冲突

一:依赖冲突的表现

  • 例1:当服务启动或者调用发生如下异常时,NoSuchMethodError,ClassNotFoundException 等。则一般是因为jar包冲突引起的,如最近项目中遇到的一个问题,就是因为com.alipay.common包发生了版本冲突,项目中实际编译打包的com.alipay.common:tracer包中RpcLogContext类没有getConnEstablishedSpan()方法引起的,虽然本地编译没有问题但服务跑起来就会报NoSuchMethodError找不到方法错误
java.lang.NoSuchMethodError: com.alipay.common.tracer.context.RpcLogContext.getConnEstablishedSpan()

image.png


  • 例2:依赖关系是app-web分别依赖project-A,project-B,然后project-A依赖1.0版本的project-common(只有hello()方法),project-B依赖project-C,project-C依赖高版本2.0的project-common(高版本中还有goodbye()方法)
  • image.png
hello,world
Exception in thread "main" java.lang.NoSuchMethodError: com.xxx.service.HelloWorld.goodbye()Ljava/lang/String;
    at com.xxx.adaptor.GoodbyeAdaptorService.goodbye(GoodbyeAdaptorService.java:11)
    at com.xxx.service.GoodbyeService.goodbye(GoodbyeService.java:11)
    at com.xxx.web.WebApp.goodbyeTest(WebApp.java:16)
    at com.xxx.web.WebApp.main(WebApp.java:23)
  • 为什么project-C依赖的project-common 2.0无法被加载,原因就是maven依赖采用的是就近依赖。从上图可以看出,project-common 1.0离app-web项目最近,因为project-common 2.0和app-web中间还隔着一个project-B。
  • 我们查看app-web项目的依赖树结构,查看命令:mvn dependency:tree -Dverbose
  • image.png
  • 由上图可以看到包依赖结构中,有两个不同版本的project-common,所以只需要排除掉一个导致报错的包即可(低版本没有方法的的包)
com.xxxproject-A1.0com.xxxproject-commoncom.xxxproject-B1.0
  • 结果
  • image.png

二:依赖冲突发生的原因

  • 大多数的依赖冲突发生的原因是因为maven的传递依赖会引入很多隐式的依赖,这些依赖可能会和我们显示依赖版本不一致。
  • image.png
  • 依赖冲突的原因总结一句话就是,依赖的版本和实际使用的版本不一致导致的。

三:依赖原则优先级

  • 原则一:最短路径优先
    • 最短路径优先: 当依赖声明不在同一个POM文件中时,或者说存在依赖传递时,路径最短的jar包将被选为最终依赖。例如下面两个依赖路径:此时Jar2.0将被选为最终依赖。
    •   image.png
  • 原则二:第一声明者优先
    • 第一声明者优先: 当依赖声明不在同一个POM文件中时,或者说存在依赖传递时,并且依赖传递长度相同时,最先声明的依赖将被选为最终依赖。此时Jar1.0将被作为最终依赖。
    • image.png
  • 原则三:覆盖优先
    • 覆盖优先: 当依赖声明在同一个POM文件中时,后面声明的依赖将覆盖前面声明的依赖。此时,Jar2.0将被选为最终依赖。
    • image.png

四:依赖冲突排查

  • 根据报错原因能初步知道是那个jar包冲突引起的NoSuchMethodError,ClassNotFoundException,但是如何排查引发问题的jar包存在哪些版本的冲突呢?或者说该怎么去查找以及解决呢?
  • 有两种办法来排查jar版本冲突,下面分别来介绍

五:Maven命令排查

  • 首先列出常用的maven依赖冲突排查命令
mvn dependency:tree 查看maven依赖树(并不能查看到所有的传递依赖) 
mvn dependency:tree -Dverbose 查看全部传递依赖依赖 ,-Dverbose参数,这时就必定是最全的了。
全是全了,但显示出来的东西太多,头晕目眩,有没有好法呢?当然有了,加上Dincludes或者Dexcludes说出你喜欢或讨厌,dependency:tree就会帮你过滤出来

如:mvn dependency:tree -Dverbose -Dincludes=com.alipay.common:tracer
  • 1、如在IDEA中可以在Terminal中输入上述命令来查看maven依赖,这种方式不会保留历史记录,下次还是要重新输入
  • image.png
  • 2、也可以用这种方式来输入命令排查,会保留历史记录,下次排查直接使用历史命令即可
  • image.png
  • 执行结果:如果在执行结果中出现 omitted for conflict with 这样的字样,就表示项目中存在jar依赖冲突,最后编译使用的jar包是omitted for conflict with字样后面的版本

  • image.png

六:Maven helper命令排查

  • 1、首先IDEA安装插件 maven helper插件(因为我已经安装了,所以没 install 的按钮了)
  • image.png
  • 2、安装完成后,在 pom 文件下方会出现这个东西
  • image.png
  • 3、点击AnaLyzer进去是这样的
  • image.png
  • 4、接下来到重点了,选中冲突选项 conflicts,这一列都是存在冲突的包
  • image.png

 

  • 5、以fastjson 为例,当然我们调错误的时候也可以直接搜索有问题的包,如下
  • image.pngimage.png
  • 6、选中右键就可以 Exclude 啦,想用1.2.28就把其他版本的Exclude掉,想用1.2.3就把其他版本的Exclude掉,是不是很方便。
  • image.png
  • image.png

 

 

 

 

七:解决方案

  • 把不需要的jar包直接
<dependency>
            <groupId>com.alipay.xxxxx</groupId>
            <artifactId>xxxxx-xxxx</artifactId>
            <version>1.0.0.20210225</version>
            <exclusions>
                <exclusion>
                    <groupId>com.alipay.xxxxx</groupId>
                    <artifactId>tracer</artifactId>
                </exclusion>
            </exclusions>
    </dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值