|
|
51CTO旗下网站
|
|
移步端
  • 好时机,我要起女同事解决Maven冲突问题

    其实在办事中经常会遇到这种冲突的题材,比如:Caused by:java.lang.NoSuchMethodError 其一特殊信息也是冲突导致的,想要消灭冲突问题就不能不得明白哪里冲突了(好像是废话)。大多数都是用 Maven 来管理依赖的 Jar,当日这篇文章主要是教授如何解决 Maven 带来的依赖冲突问题。

    笔者:尹吉欢 来源:叶猴天地| 2020-02-13 14:32

    其它一个故事起因最重要

    其它一个事情,女生都有绝对的劣势。更别提 IT 行业了,在机关中要是有女程序猿那肯定是香饽饽,备受呵护呀。

    先前有一次,一位刚来的妹妹遇到问题了,画风顿时就成为上面的图形了,群起而围之,但是最后的结果并不可以,还是得我出马(此地有点小吹牛)。

    妹子遇到的是 Jar 包冲突的题材,错误信息是 Caused by: java.lang.ClassNotFoundException,瞧错误要么就是缺少某个 Jar 包,要么就是冲突了。

    其实在办事中经常会遇到这种冲突的题材,比如:Caused by:java.lang.NoSuchMethodError 其一特殊信息也是冲突导致的,想要消灭冲突问题就不能不得明白哪里冲突了(好像是废话)。

    大多数都是用 Maven 来管理依赖的 Jar,当日这篇文章主要是教授如何解决 Maven 带来的依赖冲突问题。

    Maven 回首

    Maven 自述

    Maven 是用于构建和保管 Java 品种的工具。对于 Java 方向的来说,Maven 几乎都要接触和利用。当然也有其它的工具来代替 Maven,比如 Ant 和 Gradle。

    先前有接触过 Grails 构建的 Java Web 品种,就是用 Gradle 来做依赖管理的。至于 Ant 也在钢铁工作之时节在部分老项目中有见到过,后面几乎没见过了。

    Maven 文档地址:https://maven.apache.org[1]

    采用 Maven 可以让咱快速构建一个新的项目,并且很红火的可以集成和保管多个三方的框架。顶我们需要某个框架时可以去寻找一下这个框架的消息,下一场配置到你的品种中即可。

    追寻地址:https://mvnrepository.com[2]

    比如我们想要使用 Spring Boot,除了在 Spring 的文档中获取依赖的本子,也得以团结去寻找,慎选对应的本子,如下图:

    可以看出默认就是 Maven 的依赖方式,只要求将 dependency 整段内容复制到花色的 pom.xml 文件中即可。两侧还有好多其他的依赖方式,比如 Gradle 等。

    Maven 依托传递

    当日第一讲下如何去解决 Maven 做依赖管理的时节 Jar 包冲突的题材,在消灭之前先来了解下基本的所见所闻。

    上图展示了 Maven 的依赖传递性,第一是项目 B 官方依赖了 Spring 和 Guava 两个框架。下一场项目 A 又依赖了品种 B,故此项目 A 也会依赖 Spring 和 Guava 两个框架。

    依托传递 Jar 包选择逻辑依赖性传递会导致项目中依赖很多其他版本的 Jar,这种情况下怎么进行 Jar 包的取舍呢?

    有两个规则:

  • 不同距离,离开近优先
  • 相同距离,前者优先
  • 如下图所示,品种依赖了品种 A 和档次 B,A 和 B 离别依赖了 Guava,但是从依赖层次来看,品种 B 的层系更浅,故 Guava18.0 会把优先选择。

    顶距离相同的时节,就会优先选择定义在头里的,如下图所示,品种 A 和档次 B 都分别依赖了 Guava15.0 和 Guava18.0 的本子,但是项目 A 的程序在档次 B 的面前,故此会优先选择 Guava15.0 本子。

    穿过依赖传递性经常会导致 Jar 包冲突的题材,比如下图的品种 A 自己依赖了 Guava15.0,下一场又依赖了品种 B,品种 B 官方依赖了 Guava18.0,这样项目 A 就会同时依赖 Guava15.0 和 Guava18.0。

    如果刚好用到了高版本不兼容低版本的主意和类时,就会出现选择错误,因为 Maven 会根据依赖树的浓度来选型浅的依赖,也就是 15.0。

    冲突案例

    下就是一番典型的 Jar 包冲突问题,顶一个 Jar 有多个本子的时节,就会出现冲突。

    错误信息可以看出 com.google.common.collect.FluentIterable.concat 其一艺术找不到,脚下是副 guava-18.0.jar 中加载的,这种问题我们该怎么解决呢?

          
    1. Description: 
    2. An attempt was made to call the method com.google.common.collect.FluentIterable.concat(Ljava/lang/Iterable;Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable; but it does not exist. Its class, com.google.common.collect.FluentIterable, is available from the following locations: 
    3.     jar:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar!/com/google/common/collect/FluentIterable.class 
    4. It was loaded from the following location: 
    5.     file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar 
    6.  
    7. Action
    8. Correct the classpath of your application so that it contains a single, compatible version of com.google.common.collect.FluentIterable 

    消灭思路的悬丝诊脉

    找出冲突的 Jar,探望当前项目中依赖了甚几个本子。

    Eclipse

    在 Eclipse 官方得以双击 pom 文件,进去 Dependency 挂图,步入你要寻找的 jar 名称进行搜索,就足以看到当前项目中哪些框架依赖了你搜索的 jar,什么版本都能清楚。

    Idea

    Idea 官方得以安装 maven helper 硬件来查看相关依赖信息,默认选中 Conflicts 会展示当前项目存在冲突的依赖,当然我们也得以直接查看树形的依赖关系去分析冲突。

    Maven 命令

    不用不借助于开发工具的软件,咱们可以直接用 Maven 命令来查看当前项目的依赖关系,命令行进入到你要分析的品种目录下,推行下面的指令将分析结果保存到文件中:

          
    1. mvn dependency:tree > tree.log 

    推行完后依赖的消息结构如下:

    追寻了副 guava,意识在 smjdbctemplate 官方依赖了 18.0 本子,其一框架是我自己基于 jdbctemplate 封装的一个框架。

    消灭思路的察言观色其实很显然,错误信息已经告诉我们 18.0 官方找不到 concat 办法,故此 18.0 确认是不能用之,穿过前面的剖析,找到了直接依赖 guava.18.0.jar 的是 smjdbctemplate,消灭办法就是将 smjdbctemplate 中的 guava 排除掉。

          
    1. <dependency> 
    2.   <groupId>com.github.yinjihuan</groupId> 
    3.   <artifactId>smjdbctemplate</artifactId> 
    4.   <version>1.1</version> 
    5.   <exclusions> 
    6.     <exclusion> 
    7.       <groupId>com.google.guava</groupId> 
    8.       <artifactId>guava</artifactId> 
    9.     </exclusion> 
    10.   </exclusions> 
    11. </dependency> 

    还有就是根据依赖树的浓度度来判断当前项目依赖的是谁版本,如下图:

    18.0 是最浅的,确认是依托它,其实在 Eclipse 其中直接查看 Maven Dependencies 就足以指定当前项目依赖哪些框架和版本信息,如下图:

    顶我们排除掉 18.0 此后再来看依赖的本子是 20.0,如下图:

    根据依赖树的浓度度,20.0 和 19.0 都是一样的县团级,但是 20.0 在 19.0 眼前,故此优先选择 20.0 本子。

    再来看档次中的 pom 文件,意识 swagger 的声明顺序在 apollo 的面前。

    如果我们把顺序调整一下,这就是说就会依赖 19.0 的本子。

    总结

    交通过我仔细耐心的教授,妹子终于自己解决了遇到的题材,后面的事你们就猜去吧。😆

    这种问题其实无法避免,顶你依赖的三方框架越多的时节,冲突的可能就越大。遇到问题的时节沉下心来精心分析,借助于工具帮助你排查问题。

    当然我们在协调项目中扮依赖三方的框架,也是中心小心版本的题材,特别是对于多模块的品种,每个子模块都饰依赖不同之本子,这样很容易出题目,普通建议在父 pom 官方 dependencyManagement 来统一管理版本,子模块直接统一使用父 pom 官方定义好的本子。

    还有就是可以运用 optional 来设置可选依赖,比如说你要封装一个通用的模块 Common,其一模块中有许多通用的效应,品种 A 依托只要求采取效益 A,品种 B 依托只要求采取效益 B。每个功能都依赖了三方的 Jar,其一时节如果你不做其他处理,只要依赖了你这个通用的模块 Common,这就是说也就会间接依赖这两个效益的程序三方 Jar。其一时节可以通过设置 optional=true 来解决这个题目,我依赖了你的合同模块 Common,如果我要使用 A 效益,这就是说我必须显示依赖 A 效益需要的三方依赖才得以。

    【编纂推荐】

    1. 【NCTS碰头会回顾】阿里羽瑶:基于图像智能算法的嘴上h5页面测试提效轻量化解决方案
    2. 【NCTS碰头会回顾】搜狗科技王鹏:如何通过精准测试来解决效率黑洞
    3. 程序员解决 20 年前的增值问题
    4. 一段代码解决Colab机动掉线问题,机智到让你意外
    5. Spring消灭循环依赖的3种方法!
    【义务编辑: 武晓燕 TEL:(010)68476606】

    点赞 0
  • 消灭  Maven  冲突问题
  • 分享:
    大家都在看
    猜你喜欢
  • 订阅专栏+更多

    Kubernetes:21远处完美通关

    Kubernetes:21远处完美通关

    从小白到修神
    共29章 | king584911644

    190人口订阅学习

    Python使用场景实战手册

    Python使用场景实战手册

    Python使用场景实战手册
    共3章 | KaliArch

    122人口订阅学习

    一步到位玩儿透Ansible

    一步到位玩儿透Ansible

    Ansible
    共17章 | 骏马金龙1

    209人口订阅学习

    订阅51CTO邮刊

    点击这里查看样刊

    订阅51CTO邮刊

    51CTO劳务号

    51CTO官微

    &lt;div id="ec87585b"&gt;&lt;/div&gt;