参考:https://timup.iteye.com/blog/1725898

参考:http://ian.wang/106.htm

参考:https://www.jianshu.com/p/7b4d3453bb14?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

参考:https://blog.csdn.net/u014515854/article/details/80407024

参考:http://www.mamicode.com/info-detail-2246820.html  (查看依赖冲突解决办法)

maven学习笔记系列:https://blog.csdn.net/u011781521/article/details/79055605

一、问题

项目开发过程中,经常会遇到jar冲突,然后maven根据自己的规则进行冲突解决,导致项目在运行的过程中报错。

1、maven自动解决依赖冲突的规则是什么?

2、如何查看当前项目的maven的依赖树?

3、如何从依赖树中找到自己预期的版本,是被那个jar给覆盖了?

4、如何人工进行依赖冲突解决,达到使用目的?

二、解决问题

1、maven自动解决依赖冲突的规则是什么?

第一原则:路径最近者优先

项目A有如下的依赖关系:

A->B->C->X(1.0)

A->D->X(2.0)

则该例子中,X的版本是2.0

第二原则:路径相等,先声明者优先

项目A有如下的依赖关系:

A->B->Y(1.0)

A->C->Y(2.0)

若pom文件中B的依赖坐标先于C进行声明,则最终Y的版本为1.0

2、如何查看当前项目的maven依赖树?

//进入项目的pom.xml文件的目录下,运行如下命令
//这个是正常依赖的树
mvn dependency:tree
//这个命令是查看maven是如何解决依赖冲突的依赖树
mvn -Dverbose dependency:tree
//如果想将依赖树打印到指定文件中,则命令如下
mvn -Dverbose dependency:tree -Doutput=/Users/shangxiaofei/sxfoutput.txt

3、如何从依赖树中找到自己预期的版本,是被那个jar给覆盖了?

例子:

递归依赖的关系列的算是比较清楚了,每行都是一个jar包,根据缩进可以看到依赖的关系。
最后写着compile的就是编译成功的。
最后写着omitted for duplicate的就是有jar包被重复依赖了,但是jar包的版本是一样的。
最后写着omitted for conflict with xxxx的,说明和别的jar包版本冲突了,而该行的jar包不会被引入。比如上面有一行最后写着omitted for conflict with 3.4.6,那么该行的zookeeper:jar:3.4.8不会被引入,会引入3.4.6版本

最后写着version managed from 2.3 ;omitted for duplicate ,表示最终使用commons-pool2最终会使用2.4.2,拒绝使用<dependencyManagement></dependencyManagement>中声明的2.3版本

最后写着version managed from 1.16.8 ;表示最终使用lombok:jar:1.16.22版本

4、如何人工进行依赖冲突解决,达到使用目的?

解决重复依赖和冲突的方法:

1,修改pom文件中两个dependency元素的位置。如果两个dependency都引用了一个jar包,但是版本不同,classloader只会加载jar包在pom文件中出现的第一个版本,以后出现的其他版本的jar包会被忽略。

不建议使用该方法,因为引用不同版本的jar包本身就是很危险的。

2,使用<exclusions>标签来去掉某个dependency依赖中的某一个jar包或一堆jar包,<exclusion>中的jar包或者依赖的相关jar包都会被忽略,从而在两个dependency都依赖某个jar包时,可以保证只使用其中的一个。

可以这么写:

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.8.3.2</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>

====================Maven坐标基础知识===================

1、maven的依赖基础

<dependency>
<groupId>com.alibaba.share</groupId>
<artifactId>test</artifactId>
<version>1.4</version>
</dependency> 依赖库命名规则:
${groupId.part1}/${groupId.part2}/${version}
例:com/alibaba/share/1.4 依赖库文件命名规则:
${artifactId}-${version}-${classifier}.${type}
例:test-1.4-source.jar 注:classfier即分类器,多数的时候是用不到的,不过有写情况需要,例:
TestNG强制需要你提供分类器,以区别jdk14和jdk15
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.7</version>
<classifier>jdk15</classifier>
</dependency>

2、maven依赖范围

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>

上面的scope即约定依赖范围。 
compile:默认值,一直可用,最后会被打包 
provided:编译期间可用,不会被传递依赖,不会被打包。例:依赖于web容器中的提供的一个jar包,在编译的时候需要加入依赖(web容器还没有介入),运行的时候由web容器来提供。 
test:执行单元测试时可用,不会被打包,不会被传递依赖 
runtime:运行和测试时需要,但编译时不需要 
system:不推荐使用

3、maven依赖管理

避免不同子模块中依赖版本冲突 
在父pom中配置依赖

<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
...
<dependencies>
</dependencyManagement>

在子pom中添加依赖

<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>

dependencyManagement实际上不会真正引入任何依赖,在子pom中添加之后才会。在父pom中配置了之后,子模块只需使用简单groupId和artifactId就能自动继承相应的父模块依赖配置。如果子pom中定义了version,则覆盖management中的。

4、可选依赖

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>1.5</version>
<optional>true</optional>
</dependency>

5、依赖版本界限

要求的依赖版本>=3.8且<4.0

<version>[3.8,4.0)</version>   

要求的依赖版本<=3.8.1

<version>[,3.8.1]</version>    

要求必须是3.8.1版本,如果不是的话会构建失败,提示版本冲突。原来的写法<version>3.8.1</version>的意思是所有版本都可以,但最好是3.8.1

<version>[3.8.1]</version>   

6、排除依赖

依赖project-a但是排除掉对project-a中引入的project-b的依赖 

<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>project-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>project-b</artifactId>
</exclusion>
</exclusions>
</dependency>

替换依赖 
直接使用上一步中的排除掉,然后添加要替换进来的依赖就可以了,没有什么特殊的标志来标志这个是替换进来的。

7、版本冲突仲裁

版本仲裁规则(在maven 2.2.1版本上测试验证)
• 按照项目总POM的DependencyManager版本声明进行仲裁(覆盖),但无警告。
• 如无仲裁声明,则按照依赖最短路径确定版本。
• 若相同路径,有严格区间限定的版本优先。
• 若相同路径,无版本区间,则按照先入为主原则。

8、依赖冲突解决办法

查看那些jar包依赖了冲突包的命令

mvn dependency:tree -Dverbose -Dincludes=被依赖的包

刚才吹嘘dependency:tree时,我用到了“无处遁形”,其实有时你会发现简单地用dependency:tree往往并不能查看到所有的传递依赖。不过如果你真的想要看所有的,必须得加一个-Dverbose参数,这时就必定是最全的了。
全是全了,但显示出来的东西太多,头晕目眩,有没有好法呢?当然有了,加上Dincludes或者Dexcludes说出你喜欢或讨厌,dependency:tree就会帮你过滤出来:
引用
Dincludes=org.springframework:spring-tx
过滤串使用groupId:artifactId:version的方式进行过滤,可以不写全啦,如:

mvn dependency:tree -Dverbose -Dincludes=asm:asm

就会出来asm依赖包的分析信息:

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---
[INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT
[INFO] +- asm:asm:jar:3.2:compile
[INFO] \- org.unitils:unitils-dbmaintainer:jar:3.3:compile
[INFO]    \- org.hibernate:hibernate:jar:3.2.5.ga:compile
[INFO]       +- cglib:cglib:jar:2.1_3:compile
[INFO]       |  \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO]       \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO] ------------------------------------------------------------------------

对asm有依赖有一个直接的依赖(asm:asm:jar:3.2)还有一个传递进入的依赖(asm:asm:jar:1.5.3)

第二板斧:将不想要的传递依赖剪除掉

承上,假设我们不希望asm:asm:jar:1.5.3出现,根据分析,我们知道它是经由org.unitils:unitils-dbmaintainer:jar:3.3引入的,那么在pom.xml中找到这个依赖,做其它的调整:

<dependency>  
        <groupId>org.unitils</groupId>  
        <artifactId>unitils-dbmaintainer</artifactId>  
        <version>${unitils.version}</version>  
        <exclusions>  
            <exclusion>  
                <artifactId>dbunit</artifactId>  
                <groupId>org.dbunit</groupId>  
            </exclusion>  
            <!-- 这个就是我们要加的片断 -->  
            <exclusion>  
                <artifactId>asm</artifactId>  
                <groupId>asm</groupId>  
            </exclusion>  
        </exclusions>  
    </dependency>

再分析一下,你可以看到传递依赖没有了:

[INFO]  
    [INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---  
    [INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT  
    [INFO] \- asm:asm:jar:3.2:compile  
    [INFO] ------------------------------------------------------------------------  
    [INFO] BUILD SUCCESS

【maven】maven查看项目依赖并解决依赖冲突的问题的更多相关文章

  1. SpringBoot+Maven多模块项目(创建、依赖、打包可执行jar包部署测试)完整流程

    一,创建Maven多模块项目先建立外层父工程         File →new →project  选择Spring Initializr          Next下一步到以下页面 工程结构如下 ...

  2. maven 使用 国内镜像的方法 解决依赖下载慢

    转自:http://blog.csdn.net/banqgg/article/details/55804569 Maven是当前流行的项目管理工具,但官方的库在国外经常连不上,连上也下载速度很慢.国内 ...

  3. Maven多模块项目新建技巧-解决公共项目install之后可以在单独模块中直接编译

    说明:如果按照这种方式http://www.cnblogs.com/EasonJim/p/8303878.html,且按照常规的install方式在子项目中编译项目,那么需要先install一下par ...

  4. maven第一次创建项目太慢解决方法

    问题: 第一次用maven创建项目的时候,因为本地仓库中没有jar包,需要从中央仓库下载,所以会比较慢 解决方法: 因为从中央仓库下载默认使用的国外的镜像下载,速度比较慢,我们可以把镜像修改为从阿里云 ...

  5. IDEA maven项目中引入ojdbc依赖报红色波浪线问题的解决办法

    1.pom.xml配置文件中删除ojdbc的依赖配置后更新maven项目,然后再到本地仓库中将ojdbc这个文件夹删除 2.在网上下载ojdbc14.jar,然后改名为ojdbc14-10.2.0.2 ...

  6. 解决Maven项目中jar包依赖冲突问题

    版本冲突的解决方案 [1]调节原则 [1]路径最短者优先原则 [2]路径相同时,先声明者优先原则 [2]排除原则:用于排除某项依赖的依赖jar包 <dependency> <grou ...

  7. maven中import scope依赖方式解决单继承问题的理解

    在maven多模块项目中,为了保持模块间依赖的统一,常规做法是在parent model中,使用dependencyManagement预定义所有模块需要用到的dependency(依赖) <d ...

  8. 利用mvn/maven如何检查依赖冲突,并解决依赖冲突

    mvn/maven如何检查依赖冲突,并解决依赖冲突 如图,点击图示位置,就可以把整个项目的依赖关系展示出来 在图里选中一个artifact,则所有依赖该artifact的地方都会一起连带出来突出显示, ...

  9. Maven 基础(二) | 解决依赖冲突的正确姿势

    一.依赖原则 假设,在 JavaMavenService2 模块中,log4j 的版本是 1.2.7,在 JavaMavenService1 模块中,它虽然继承于 JavaMavenService2 ...

随机推荐

  1. jenkins部署web项目到tomcat(五)

    (1)maven构建web项目 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...

  2. Java并发编程_wait/notify和CountDownLatch的比较(三)

     1.wait/notify方法 package sync; import java.util.ArrayList; import java.util.List; public class WaitA ...

  3. 最短路径:Dijkstra & Floyd 算法图解,c++描述

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. HP Instant Information

    HP Instant Information before HP-UX 11i v3 <管理系统和工作组:HP-UX系统管理员指南> After HP-UX 11i v3 <HP-U ...

  5. loadrunner json中文无法识别问题

    http://blog.sina.com.cn/s/blog_6ff7a3b50101awmy.html

  6. loadrunner http协议性能测试脚本编写

    性能测试其实测的就是接口的性能,不管是用工具录制还是自己写,都是围绕接口的,录制也是把接口录制下来而已,但是录制下来的脚本比较乱,会把很多相关的请求都录下来. 在这里我们手动写HTTP协议的get.p ...

  7. 【重大更新】DevExpress WinForms v18.2新版亮点(七)

    买 DevExpress Universal Subscription  免费赠 万元汉化资源包1套! 限量15套!先到先得,送完即止!立即抢购>> 行业领先的.NET界面控件2018年第 ...

  8. 关于Java的特点之封装

    抽象 1.简单理解 我们在前面去定义一个类时候,实际上就是把一类事物的共有的属性和行为提取出来,形成一个物理模型(模版).这种研究问题的方法称为抽象. 封装--什么是封装 封装就是把抽象出来的数据和对 ...

  9. leetcode31题:下一个排列

    实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常数空间. ...

  10. python基础题型一

    一.执行Python脚本的两种方式 #python name.py   Python解析器 #chmod +x name.py 二.简述位.字节的关系 1Byte=8bit 三.简述ascii.uni ...