当前位置: 首页 > 科技观察

好机会,想帮女同事解决Maven冲突问题

时间:2023-03-21 20:23:34 科技观察

任何故事的事业都是最重要的任何职业,女生都有绝对的优势。别说IT行业了,如果部门里有一个女程序员,肯定是宠爱的,肯定是被呵护的。之前有个刚来的妹子遇到了问题,画风突然变成了上图,周围人都围了上去,但是最后的效果并不理想,所以还是不得不做了(这里有点吹牛).妹子遇到的是Jar包冲突的问题。错误消息是由:java.lang.ClassNotFoundException引起的。错误要么是缺少某个Jar包,要么是冲突。其实在工作中经常会遇到这种冲突问题,比如:Causedby:java。大多使用Maven来管理依赖的Jar。今天的文章主要讲解如何解决Maven引起的依赖冲突问题。MavenReviewMaven自述文件Maven是用于构建和管理Java项目的工具。对于Java方向,几乎都是接触和使用Maven。当然,还有其他工具可以替代Maven,比如Ant和Gradle。之前接触过Grails构建的JavaWeb项目,使用Gradle进行依赖管理。至于Ant,刚开始工作的时候在一些老项目里见过,后来就基本没见过了。Maven文档地址:https://maven.apache.org[1]使用Maven可以让我们快速的构建一个新的项目,并且非常方便的集成和管理多个三方框架。当我们需要某个框架的时候,可以搜索这个框架的资料,然后在你的项目中进行配置。搜索地址:https://mvnrepository.com[2]比如我们要使用SpringBoot,除了在Spring文档中获取依赖版本外,还可以自己搜索,选择对应的版本,如图在下图中:可以看到默认的是Maven的依赖方式,只需要将依赖的全部内容复制到项目的pom.xml文件中即可。右边还有很多其他的依赖方式,比如Gradle等等。MavenDependencyTransfer今天主要讲一下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.0。冲突案例下面是一个典型的Jar包冲突问题。当一个Jar有多个版本时,就会发生冲突。报错信息可以看com.google.common.collect.FluentIterable.concatThismethodcannotbefound。它当前是从guava-18.0.jar加载的。我们如何解决这个问题?描述:尝试调用方法com.google.common.collect.FluentIterable.concat(Ljava/lang/Iterable;Ljava/lang/Iterable;)Lcom/google/common/collect/FluentIterable;butitdoesnotexist.Itsclass,com.google.common.collect.FluentIterable,isavailablefromthefollowinglocations:jar:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar!/com/google/common/collect/FluentIterable.class它是从以下加载的location:file:/Users/yinjihuan/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jarAction:更正你的应用程序的类路径,使其包含一个单一的、兼容版本的com.google.common.collect.FluentIterable找到冲突的Jar并查看哪些依赖于当前项目版本。Eclipse在Eclipse中,可以双击pom文件进入Dependency视图,输入你要搜索的jar的名称,就可以看到当前项目中有哪些框架依赖了你搜索的jar,你可以知道是什么版本。在IdeaIdea中可以安装mavenhelper插件查看相关依赖信息。Conflicts默认选中,显示当前项目中的冲突依赖项。当然,我们也可以直接查看树形依赖关系来分析冲突。Maven命令不需要开发工具的插件。我们可以直接使用Maven命令来查看当前项目的依赖。命令行进入你要分析的项目目录,执行如下命令将分析结果保存到文件:mvndependency:tree>tree.log执行后,依赖信息结构如下:搜索guava后,我发现smjdbctemplate依赖18.0版本。这个框架是我自己基于jdbctemplate封装的一个框架。解决的方法其实很明显。报错信息已经告诉我们18.0找不到concat方法,所以18.0一定不能用。通过前面的分析,我们发现smjdbctemplate直接依赖于guava.18.0.jar。解决方案是从smjdbctemplate中排除番石榴。com.github.yinjihuansmjdbctemplate1.1com.google.guavaguava另外就是根据依赖树的深度来判断当前项目依赖哪个版本,如下图:18.0最浅的,一定是依赖它,其实可以直接在Eclipse中查看MavenDependencies来指定当前项目依赖了哪些框架和版本信息,如下图:当我们排除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函数需要的三方依赖。