怎么处理maven依赖冲突?

大家好,我是IT修真院上海分院第5期学员,一枚正直善良的JAVA程序员。

今天给大家分享一下,修真院官网JAVA任务7中的深度思考,怎么处理maven依赖冲突?

一、背景介绍

我查看的讲依赖冲突的教程中提到,依赖冲突常见的错误是出现很多奇怪的错误,如果有一定的开发经验了,当出现奇怪报错时就需要考虑依赖冲突了。还有一点,依赖冲突的解决在多模块的大型项目中很重要,但是单model的项目,中基本maven自己就解决了。所以初学者不要过多关注,就是以后工作了,这些事情也不会交给新手的,况且许多公司的框架可能都是多年不变的,更不可能让你动了。

maven的依赖冲突是怎么产生的?

依赖冲突自然是项目中依赖的jar包出现冲突了,具体体现为相同的groupId和artifactId,但是出现了不同的version,所以才会出现冲突。而产生冲突的原因是依赖传递引起的。我们都知道,做项目时需要引入各种各样的依赖,而这些依赖本身也是一些项目,所以它们本身也需要依赖其他jar包。所以在maven做项目管理时,maven自动将这些jar包所依赖的jar查询并导入进来了。这就势必导入一些版本冲突的jar包。


二.知识剖析

对此maven有自己的策略来解决依赖冲突,而处理冲突的功能是“依赖仲裁(dependency mediation)”。在maven2.0的版本中采用了策略“nearest wins”。这是什么呢?这又涉及到新的概念,层、深度或路径。这三个的解释差不多,都是用来描述依赖所处的位置。先看下下面的部分文档:

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ java-task7 ---
[INFO] com.ptteng:java-task7:war:1.0-SNAPSHOT
[INFO] +- org.slf4j:slf4j-api:jar:1.7.12:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.7.12:compile
[INFO] |  \- (org.slf4j:slf4j-api:jar:1.7.12:compile - omitted for duplicate)

[INFO] +- org.apache.tiles:tiles-extras:jar:3.0.5:compile
[INFO] |  +- org.apache.tiles:tiles-core:jar:3.0.5:compile
[INFO] |  |  +- org.apache.tiles:tiles-api:jar:3.0.5:compile
[INFO] |  |  |  \- (org.slf4j:slf4j-api:jar:1.7.6:compile - omitted for conflict with 1.7.12)

[INFO] |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.21:compile

这是我用maven命令‘mvn dependency:tree’导出的项目依赖树。同时这个命令添加了参数‘-Dverbose’,所以内容比较多。从这一段就可以看出层、深度或路径的概念。尤其是这句“org.slf4j:slf4j-api:jar:1.7.6:compile - omitted for conflict with 1.7.12“就是maven自动采用“nearest win”的策略,用1.7.12的版本代替了1.7.6的版本,从而解决了多个org.slf4j:slf4j-api:jar版本冲突的问题。因为在项目中声明了org.slf4j:slf4j-api:jar:1.7.12,所以这就属于最浅的层了。

但是如果遇到相同层的怎么办?直到maven2.0.9才提出了”by order"的策略,就是声明的前后顺序,在前的赢。

处理maven自动处理依赖冲突,还可以项目开发者控制。maven提供的功能是:dependency management,dependency scope,excluded dependencies,optional dependencies。这些功能在pom.xml文件中都有对应标签提供了这些功能。分别是<dependencyManagement>(放置<dependencies>外面),<scope>(在groupId的同级),<exclusions><exclusion></exclusion></exclusions>(也是和groupId同级的,里面填写不包含的groupId,artifactId),<optional>。

其中scope的值有compile(默认值),provided,runtime,test,system,import。每个用处就是限定了该依赖jar包的使用范围,并决定依赖是否传递到其他层。具体差别可以参考maven官网讲依赖传递机制的内容。里面也提供了一些pom.xml文件的例子。

接下来讲下查看依赖冲突的方式,首先是maven的命令行查看依赖树,就是前面提到的命令“mvn dependency:tree”,需要的参数有“-Dverbose”,可以自己对比下输出的信息全面程度。这时信息很多,查看起来不方便,需要另外一个参数”-Dincludes=groupId:artifactId“可以查看指定jar包的依赖冲突,这时查看就比较方便了。同时还可以导出到本地文件。在命令的最后添加“  > filepath/filename.filetype”这样就输出到指定文件了,不写文件路径,默认导出到项目的根目录。

intellij idea中也可以查看,右键maven -》show dependencies,或者是在maven的tool button中选择那个树形的图标可以直接打开,依赖依赖树窗口。在里面可以使用ctrl+f搜索指定jar包,确定后会出现好多红色虚线,上面写着冲突的版本号。之后右键选择exclude或是在pom.xml中添加exclusions元素,具体怎么写自己多试试,我的效果不太好就不说了。

到了这时还是会小概率的出现些漏网之鱼。我看有个教程写了个方法,感兴趣的可以学习下。

三、常见问题

1、什么是依赖冲突?

2、maven解决依赖冲突的机制?

3、依赖范围有哪些?

四.解决方案

1、答:依赖冲突是由依赖传递引起的版本冲突。项目中的依赖都有自身的依赖,这些依赖会传递到当前项目中。然后根据依赖版本的不同,就导致了依赖冲突。

2、答:maven有两种自动的解决依赖冲突的机制:最短路径和by order优先。前者是产生依赖冲突的依赖采用离项目最近(就是路径最短的)的那个版本。后者是指相同路径深度时,采用最先声明的那个版本。

还有手动控制的禁止依赖传递和取消依赖的方法。

3、答:compile,provided,runtime,test,system,import。

五。编码实战

六、参考文献

http://www.cnblogs.com/davenkin/p/advanced-maven-resolve-dependencies-conflicts.html

https://www.cnblogs.com/chowmin/articles/3891199.html

https://github.com/davenkin/maven-dependency-conflict-demo

http://ian.wang/106.htm

8.更多讨论

鸣谢

感谢观看,如有出错,恳请指正

七.更多讨论

详见视频

腾讯视频

感谢大家观看

今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

我的邀请码链接:http://www.jnshu.com/login/1/20535344

使用我的优惠码优惠多多!

我的邀请码:20535344


技能树.IT修真院

“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。

这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。快来与我一起学习吧~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值