maven 不同版本jar冲突问题的解决办法
今天想把dubbo整合到项目中,本来项目是框架为ssm的maven项目。在引入dubbo之前项目正常运行。但是在引入dubbo以及zookeeper之后,报了异常。发现是jar包冲突问题,之前遇到过一次没有理会,这次整理一下。
1.maven为什么会发生jar包冲突问题?
maven管理jar是其核心功能之一,maven对于你要引入的jar在解析的时候会把此jar内部依赖的jar同样进行解析,接着会对内部依赖的jar依赖的jar进行解析…….直到不再存在依赖的jar的时候,会把这些jar全部引入。所以我们只需要引入自己需要的jar,而此jar依赖的jar交给maven帮我们找到并引入。减少了我们去寻找其依赖的jar以及找到对应版本这项工作(要知道这项工作是很费时间的)。但是这样也引发了一个问题,就是我们引入的jar所依赖的jar版本可能不同,而Maven在解析pom文件时,对于同一个jar包只会保留一个,这样便避免因引入两个jar包导致的工程运行不稳定的问题。那么留下的那个jar在使用过程中就可能因为版本不通而引发报错,这便是jar冲突问题发生的根源。
2.如何解决此问题。
要想解决就应该注意到Maven在解析pom文件时,对于同一个jar包只会保留一个,而留下的这一个不是我们需要的才会出现意料之外的报错。那么我们就要知道maven是如何决定保留那个jar的。
2.1 在有多个版本的jar依赖时maven是如何决定保留哪个的。
1优先按照依赖管理元素中指定的版本声明,此时下面的两个原则都无效。
2若无版本声明,则按照“短路径优先”的原则,即选择依赖树中路径最短的版本。
3若路径长度一致,则按照“第一声明优先”的原则,即选择POM中最先声明的版本。
下面是我主pom文件中的一些配置,使用的是第一个原则(强烈推荐,因为基本没发生过问题)。
<!--定义此文件使用的全局参数**************开始*****************-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--项目统一字符集,此配置会被maven自动识别而使用,当然也可以在本文件其他位置使用。-->
<!--下面的这些参数将在本配置文件中作为全局变量使用-->
<springframework.version>4.2.4.RELEASE</springframework.version><!--spring的版本控制-->
<atom.version>1.1-SNAPSHOT</atom.version><!--miniUi的版本控制-->
<cxf.version>3.1.11</cxf.version><!--前端优化框架cxf的版本号-->
</properties>
<!--定义此文件使用的全局参数**************结束*****************-->
<!--推荐引入jar的顺序:前台框架->->->前台优化框架->->->spring框架(包括MVC)->->->mybatis框架->->->
一些工具jar(1:测试使用如junit、log,2:任务调度如Quartz、监控,3系统处理标准文档如poi、4调用外部系统如httpclient,Json) -->
<!--使用dependencyManagement当子项目使用父类引入的jar时:若声明版本号则子项目单独从数据仓库引入jar,若不声明版本号,则使用父类的jar(用来确保引用的jar版本统一)
并且使用dependencyManagement时,只引入其声明的的jar,但不使dependencyManagement时,子项目会引入所有的父项目jar-->
<dependencyManagement>
<!--下面引入整个项目(包括主项目和子项目使用的jar的集合~~这里需要声明版本号来引入jar,而子项目通过继承引用这里的jar)-->
<dependencies>
<!--spring begin-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>a</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>f</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--spring end-->
</dependencies>
</dependencyManagement>
“短路径优先”的原则是指如下(->为依赖):
比如a.jar->b.jar->c.jar->d.1.0.jar
而f.jar->g.jar->d.1.3.jar
那么d.1.3.jar的路径短与d.1.0.jar则保留d.1.3.jar。
“第一声明优先”的原则:
这是在“短路径优先”的原则并未决定出保留哪个的时候生效,即
a.jar->b.jar->d.1.0.jar
f.jar->g.jar->d.1.3.jar
而在pom中a的声明优先与f的声明那么就保留优先声明的依赖d.1.0.jar。
所以根据这三原则基本可以解决jar冲突问题。当然maven还提供了另一种方式:使用<exclusion>标签。
那就是你可以在声明中手动排除可能导致冲突的依赖jar,例如我排除dubbo中对spring的依赖的方式。
<!-- dubbo begin -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<!-- dubbo end -->
今天就先记录到这,下次有时间把maven检测jar冲突的插件集成及使用方式整理一下。