https://blog.csdn.net/sinat_39789638/article/details/78005945
共有四种解决方式:
★ 自动处理:
1、第一声明优先原则:(路径一样长)
在pom.xml配置文件中,如果有两个名称相同 版本不同 的依赖声明
,那么先写的会生效
。
所以,先声明自己要用的版本的jar包即可。
例如:
A中的 commons-io的版本为2.4
B中的commons-io的版本为2.0
C到达A为 C->A
C到达B为 C->B
则看pom文件中,依赖的两个工程 谁在前面 就是 用哪个版本
这里使用的common-io为2.4版本
<dependency>
<groupId>org.lonecloud.A</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--C依赖于B但是会将A的依赖传递进来 -->
<dependency>
<groupId>org.lonecloud.B</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 此标签的作用是可以将B的传递依赖关系A不传递给C -->
<!-- <exclusions> <exclusion> <groupId>org.lonecloud.A</groupId> <artifactId>A</artifactId>
</exclusion> </exclusions> -->
</dependency>
2、路径近者优先: 谁离得最近就使用谁的依赖jar包
直接依赖 优先于 传递依赖
,如果 传递依赖的jar包 版本冲突了
,那么可以自己声明一个 指定版本的 依赖jar
,即可解决冲突
。
例如:
C到达A为 C->B->A
C到达B为 C->B
A中的 commons-io的版本为2.4,B中的commons-io的版本为2.0,C中依赖于B,B依赖于A,则C的junit的包为2.0版本,因为依赖的短路优先。
★ 手动处理:
3、排出原则:
传递依赖冲突时,可以 在不需要的jar 的传递依赖中 声明排除
,从而解决冲突。
例子:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.24</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>
4、版本锁定原则(最常使用)
在配置文件pom.xml中先声明 要使用哪个版本 的 相应jar包
,声明后 其他版本的jar包 一律不依赖
。解决了依赖冲突。
例子:
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<struts.version>2.3.24</struts.version>
</properties>
<!-- 锁定版本,struts2-2.3.24、spring4.2.4、hibernate5.0.7 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
依赖范围有哪些?
compile,provided,runtime,test,system,import。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
看上面的xml片段,会发现一个新东西scope。这个标签的意思就是当前插件依赖的范围
。
在开发中我们把第三方jar放入到classpath中
,就能够调用第三方的类和方法。
maven有3中classpath分别是
- 编译
- 测试
- 运行
上面的xml片段中scope的值为test,也就是说这个构建只存在于测试环境
中。所以scope的值
就是控制与三种classpath的关系
。
scope的值
- compile
默认的范围
,编译、测试、运行
都有效。 - provided
编译和测试
时有效,最后是在运行的时候不会被加入
。官方举了一个例子。比如在JavaEE web项目中我们需要使用servlet的API,但是Tomcat中已经提供这个jar
,我们在编译和测试的时候需要使用这个api,但是部署到tomcat的时候,如果还加入servlet构建就会产生冲突,这个时候就可以使用provided。 - runtime 在
测试和运行
时有效。 - test 在
测试
时有效。 - system 与本机系统相关联,可移植性差。
编译和测试
时有效。 - import
导入的范围
,它只在使用dependencyManagement中,表示 从其他pom中 导入dependecy的配置
。
举个import栗子:就是把A中的构建导入到B中。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>B</artifactId>
<packaging>pom</packaging>
<name>B</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>maven</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>