maven依赖冲突查找

Posted 十一路客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了maven依赖冲突查找相关的知识,希望对你有一定的参考价值。

转载自:http://blog.csdn.net/loongshawn/article/details/50831890

1.0 背景

maven工程在部署时,有时候大家会碰到这种情况:自己在POM中标明的是引用版本A的jar包,实际打包后却是引用版本B的jar包,或者打的war包中的lib目录下会出现pom.xml中并未引用的jar包。下面就以我遇到的情形来说明。

2.0 实例说明

2.1 案例

案例:pom中指定httpclient-4.4.jar,但实际打包后加载的是httpclient-4.3.6.jar

这个情况之前一直没有发现,直到最近在集成阿里云oss功能才有所察觉。因为每次部署线上服务器时,总是报如下异常:

2016-03-07-23-37 [http-nio-7001-exec-9] [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]] [ERROR] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.NoClassDefFoundError: org/apache/http/conn/ssl/NoopHostnameVerifier] with root cause
  java.lang.ClassNotFoundException: org.apache.http.conn.ssl.NoopHostnameVerifier
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at com.aliyun.oss.common.comm.DefaultServiceClient.createHttpClientConnectionManager(DefaultServiceClient.java:230)
        at com.aliyun.oss.common.comm.DefaultServiceClient.<init>(DefaultServiceClient.java:78)
        at com.aliyun.oss.OSSClient.<init>(OSSClient.java:244)
        at com.aliyun.oss.OSSClient.<init>(OSSClient.java:204)
        at com.autonavi.oss.client.DefaultOSSClient.<clinit>(DefaultOSSClient.java:12)
        at com.autonavi.oss.put.OSSUpload.put2(OSSUpload.java:61)
        at com.autonavi.utils.gaokuai.FileUpload.fileUpload(FileUpload.java:229)

上面这个异常是说明缺少NoopHostnameVerifier这个类。查了下,这个类是httpclient-4.4.jar版本中的类。

工程的pom中明明已经制定了httpclient-4.4.jar的版本,按道理应该不会出现找不到类的异常。

到目前为止,可以判断是maven依赖冲突,既然有冲突,需要找到冲突的源在哪个依赖,然后过滤掉这个依赖即可。接下来进入本地的工程目录,执行以下命令,获取依赖树:

mvn dependency:tree -Dverbose
注意不能仅仅是mvn dependency:tree这个命令,因为这样看不出深层次的依赖引用关系,后面必须加上-Dverbose,以下为依赖树截取部分,从中可以看出aliyun-sdk-oss-2.1.0:jar包依赖httpclient-4.3.6.jar的包。

com.aliyun.oss:aliyun-sdk-oss:jar:2.1.0:compile
[INFO] | +- (org.apache.httpcomponents:httpclient:jar:4.3.6:compile - version managed from 4.4; omitted for conflict with 4.4)
[INFO] | +- org.jdom:jdom:jar:1.1:compile
[INFO] | \\- net.sf.json-lib:json-lib:jar:jdk15:2.4:compile
[INFO] | +- commons-beanutils:commons-beanutils:jar:1.9.2:compile (version managed from 1.8.0)
[INFO] | | \\- (commons-collections:commons-collections:jar:3.2.1:compile - omitted for duplicate)
接下来,我们先在pom中过滤掉这个httpclient-4.3.6.jar的包:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.2.0</version>        
    <exclusions> 
        <exclusion>                            
         <groupId>org.apache.httpcomponents</groupId> 
        <artifactId>httpclient</artifactId>                    
        </exclusion> 
    </exclusions> 
</dependency>   
注意,过滤掉冲突jar包,使用如下标注:

<exclusions> 
        <exclusion>                            
        <groupId>111</groupId> 
        <artifactId>111</artifactId>                   
        </exclusion> 
</exclusions> 
过滤掉后,重新执行mvn dependency:tree -Dverbose,得到的依赖树里面再没有说引用httpclient-4.3.6.jar,然后依次执行mvn clean和mvn install -Dmaven.test.skip=true,target中得到如下文件:

解压:

发现里面的lib目录依然加载的是httpclient-4.3.6.jar,这下子晕了,究竟问题出在哪里,这个maven工程干嘛一直加载这个版本的httpclient包。

至此,可以判断,问题的根结不是在pom依赖上面。而是其他位置,我尝试删除本地库中的httpclient-4.3.6.jar的包。然后重新执行上述maven构建命令,发现工程会自动加载这个版本的包,会不会是打包插件版本的问题:

[INFO]
[INFO] --- spring-boot-maven-plugin:1.1.9.RELEASE:repackage (default) @ rus-api-services ---
[INFO]
[INFO] --- maven-assembly-plugin:2.2-beta-5:single (make-assembly) @ rus-api-services ---
[INFO] Reading assembly descriptor: src/main/assembly/assembly.xml
Downloading: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.pom (6 KB at 1.9 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.jar
Downloaded: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.jar (579 KB at 157.6 KB/sec)
[INFO] Building tar : /Users/xiaolong/Documents/workspace/rus-api-services/target/rus-api-services.tar.gz
[INFO]
[INFO] --- maven-install-plugin:2.5.1:install (default-install) @ rus-api-services ---
pom中配置的打包插件maven-assembly-plugin如下,版本是2.2-beta-5:

在网上查了下,其最新版本是2.5.3,2.2-beta-5版本有点老了,好了,先替换为新版本,试一试,果然加载了正确的httpclient-4.4.jar。

最后部署线上环境,服务运行OK。

个人补充:

查找某个包的依赖关系命令

mvn dependency:tree -Dverbose -Dincludes=com.xxx.xxx:artifactID
当然也不要一遇到找不到类或找不到方法的异常,就觉得是包冲突,也有可能是引用包的版本不对,导致方法使用报错,不同版本的包同一个方法引用方式可能会变化;

比如说觉得是引入的log4j-core jar包引起的冲突,出现找不到方法的异常,可以先把这个包去了,看看是不是还是同样的错误,如果是找不到该方法对应的类了,说明此异常不是包冲突引起的,因为出错的地方确实是引用了这个包,不是其他版本的包。



以上是关于maven依赖冲突查找的主要内容,如果未能解决你的问题,请参考以下文章

Maven怎么处理引用的jar版本冲突

Maven怎么处理引用的jar版本冲突

maven依赖冲突查找

maven依赖冲突查找

冲突的传递依赖关系在 Maven 中是一个严重的问题吗?

如何删除maven中冲突的jar包