好机会,我要帮女同事解决Maven冲突问题
任何一个故事起因最重要
任何一个职业,女生都有绝对的优势。更别提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
使用Maven可以让我们快速构建一个新的项目,并且很方便的可以集成和管理多个三方的框架。当我们需要某个框架时可以去搜索一下这个框架的信息,然后配置到你的项目中即可。
搜索地址:https://mvnrepository.com
比如我们想要使用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中加载的,这种问题我们改怎么解决呢?
Description:
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:
jar:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar!/com/google/common/collect/FluentIterable.class
It was loaded from the following location:
file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar
Action:
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命令来查看当前项目的依赖关系,命令行进入到你要分析的项目目录下,执行下面的命令将分析结果保存到文件中:
mvn dependency:tree > tree.log
执行完之后依赖的信息结构如下:
搜索了下guava,发现在smjdbctemplate中依赖了18.0版本,这个框架是我自己基于jdbctemplate封装的一个框架。
解决思路之察言观色
其实很明显,错误信息已经告诉我们18.0中找不到concat方法,所以18.0肯定是不能用的,通过前面的分析,找到了直接依赖guava.18.0.jar的是smjdbctemplate,解决办法就是将smjdbctemplate中的guava排除掉。
<dependency>
<groupId>com.github.yinjihuan</groupId>
<artifactId>smjdbctemplate</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</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的版本。
总结
通过我仔细耐心的讲解,妹子终于自己解决了遇到的问题,后面的事你们就猜去吧。
好机会,我要帮女同事解决Maven冲突问题的更多相关文章
- jQuery基础之(五)jQuery自定义添加"$"与解决"$"的冲突
1.自定义添加$ 从上面四篇文章我们看到jQuery的强大,但无论如何,jQuery都不可能满足所有用户的需求,而且有一些需求十分小众,也不适合放到整个jQuery框架中,正是因为这一点,jQuery ...
- 【maven】maven查看项目依赖并解决依赖冲突的问题
一.问题 项目开发过程中,经常会遇到jar冲突,然后maven根据自己的规则进行冲突解决,导致项目在运行的过程中报错. 1.maven自动解决依赖冲突的规则是什么? 2.如何查看当前项目的maven的 ...
- 解决 Git 冲突的 14 个建议和工具
Git 非常善于合并代码.代码的合并在本地完成,快速而且灵活.正常情况下每次从不同分支合并内容时,冲突有可能会发生.通常解决冲突很简单,就如同知道(如何)选择(保留)重要的更改一样,而有时解决冲突则需 ...
- Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)
一.背景 在我上一篇文章<Spring Cloud开发人员如何解决服务冲突和实例乱窜?>中提到使用服务的元数据来实现隔离和路由,有朋友问到能不能直接通过IP来实现?本文就和大家一起来讨论一 ...
- IDEA 解决 Maven 依赖冲突的高能神器,这一篇够不够?
1.何为依赖冲突 Maven是个很好用的依赖管理工具,但是再好的东西也不是完美的.Maven的依赖机制会导致Jar包的冲突.举个例子,现在你的项目中,使用了两个Jar包,分别是A和B.现在A需要依 ...
- 大厂面试必问!HashMap 怎样解决hash冲突?
HashMap冲突解决方法比较考验一个开发者解决问题的能力. 下文给出HashMap冲突的解决方法以及原理分析,无论是在面试问答或者实际使用中,应该都会有所帮助. 在Java编程语言中,最基本的结构就 ...
- 解决maven依赖冲突,这篇就够了!
一.前言 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成了包版本冲突. 依赖冲突的原因 我们在maven项目的pom中 一般会引用许许多多的dependency.例如 ...
- 如何解决Maven和SBT下载Jar包太慢
国内:如何解决Maven和SBT下载Jar包太慢 Maven 远程仓库 <mirror> <id>ui</id> <mirrorOf>central&l ...
- 解决maven生成的web项目下的servlet.jar与tomcat自带servlet.jar冲突的问题
使用maven生成web工程后,编译需要下servlet-api.jar和jsp-api.jar文件. pom文件中的写法为: <dependency> <groupId>ja ...
随机推荐
- 浅析Java hashCode()方法
散列码(hash code)是由对象导出的一个整数值. 散列码没有规律,两个不同的对象x和y,x.hashCode()与y.hashCode()基本上不会相同. public static voi ...
- [Oracle]Oracle的闪回归档
Oracle的闪回归档 场景需求,由于管理数据库的一些核心表,在实施初期会有人为误删除的问题.Oracle 11gR2提供了闪回归档的特性,可以保证不用RMAN来恢复误删除的数据.实践如下: 1.创建 ...
- spring 与mybatis 整合
步骤: pom文件添加依赖 创建包结构 添加application.yml, 配置数据库信息 使用mybatis-gennerator 生成三个文件 实体类 接口类 xml 文件 错误信息 xml 绑 ...
- echo 传义序列
echo 传义序列:\a 警示字符\b 退格\c 输出中忽略最后的换行符\f 清屏\n 换行\r 回车\t 水平制表符\v 垂直制表符\\ 反斜杠字符\0ddd 将字符表示成1到3位的八进制数值
- linux各目录及重要目录的详细介绍
1 目录说明 根目录 (/) /bin bin是Binary的缩写, 这个目录存放着最经常使用的命令,比如ls,cat,mkdir等 /dev dev是Device(设备)的缩写, 该目录下存放的是L ...
- spring boot中使用freemarker
在做Java web开发领域,web模板引擎主要有jsp.freemarker.velocity,其中freemarker是我们常用的一种,在spring boot中使用的freemarker的方法可 ...
- less实现if else
less没有我们平常使用的if,else条件判断,而是用when来实现这种用法 1.比如我们要设置宽度 宽度可以百分比,也可以是像素,当是百分比时做对应处理,当是px时做另一种处理,这时候就需要用wh ...
- MATLAB生成正弦波
要求:选定采样频率,生成不同频率的正弦波 程序: f1=100;%生成正弦波的频率 fs=1000;%采样频率 N=100;%采样点数 n=0:N-1; t=n/fs;%时间序列 y=sin(2*pi ...
- java动态代理、Proxy与InvocationHandler
看了好多关于代理的文章,理解和整理一下. 1.代理的基本构成 抽象角色:声明真实对象和代理对象的共同接口,这样可在任何使用真实对象的地方都可以使用代理对象. 代理角色:代理对象内部含有真实对象的引用, ...
- 案例分析丨谷歌设计冲刺 4 天决定 Clips 的功能特性
这次为大家带来Google冲刺日程案例,之前案例分析可以戳对应文字直达:ING集团.音乐流媒体Spotify.美国知名超市Target 作为一款工具类产品,谷歌十分注重产品候选人的技术背景,同时也看重 ...