httpclient与httpcore版本不匹配导致的编译问题
一、起因
maven编译报错
[ERROR] 无法访问org.apache.http.annotation.ThreadSafe
找不到org.apache.http.annotation.ThreadSafe的类文件
看本地的确不存在ThreadSafe这个文件,为什么会出现这个情况呢,升级之前还不存在这个问题,怀疑是jar包版本冲突导致的。
Google了下发现ThreadSafe是httpcore 4.4.4中的一个注解文件,将pom中httpcore的版本修改为4.4.4之后错误消失。
问题消失了不代表事情就可以结束了,原因是什么,为什么会出现这个问题? 做技术要有打破砂锅问到底的精神。
看项目中有很多文件有用到ThreadSafe这个注解,主要是有两个jar包,一个是httpclient
, 一个是它自己所在的包httpcore
。查看httpclient的pom.xml
,写的也比较明确,httpclient会依赖于httpcore包.
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<scope>compile</scope>
</dependency>
...
</dependencies>
groupId
, artifactId
比较容易理解,用于确定jar包的坐标,<scope>
表示范围,<version>
在哪儿呢?
查看httpclient在META-INF/DEPENDENCIES
中写明了Apache HttpCore org.apache.httpcomponents:httpcore:jar:4.4.4
。需要依赖于4.4.4的版本。我怀疑DEPENDENCIES文件只是起到一个说明作用,并不会做什么动作。应该是这样的,本身我的项目是spring-boot的,spring boot支持对jar包的版本进行统一管理,这个不在本章展开。
二、关于scope
我们在httpclient中看到了dependency的依赖范围是compile
,这个scope
还有哪些枚举值呢? 都代表什么意思? scope
有6个枚举值, 分别如下
-
compile
, 默认值。表示这个依赖的jar包需要在build、test、run的时候都在classPath中 -
test
, 跑单测的时候会用到这个依赖包 -
system
, 依赖本地jar包,不从maven仓库中获取。如果使用system scope,则在<dependency>
配置块中需要增加<systemPath>${basedir}\war\WEB-INF\lib\extDependency.jar</systemPath>
的说明。 -
import
, 只会出现在dependencyManagement
部分,dependencyManagement
用于“声明”项目所需要的依赖(但不引用),主要为了解决maven没法做到多继承的场景,比如我的模块要继承多个父pom,这个是没法做到的。如果在一个project里边有100个module,每个module的版本都在一个parent pom里边维护的话,太混乱了。这时可以分开把不同类型的依赖包放到不同的"管理pom文件"中(<dependency>
的<type>
是pom)进行管理,各个子module分别去import这些pom,这个理念有点类似于interface
,区别于parent class
。 -
providerd
, 跟compile很像,需要在build、test时在classPath下,而run的时候不需要,因为已经有容器提供这个包的服务。 -
runtime
, 无需编译,但是该依赖的jar包出现在其他的classPath下,可以用于test,run服务
参考:
三、dependencies和dependencyManagement
要理解dependencyManagement
需要知道它出现的背景,在一个多模块的工程中,各模块可能会依赖相同的jar包,之前是在每个模块的pom.xml
中通过具体jar包的坐标来指定,但可能会造成不同版本之间jar包冲突导致的运行问题。
解决这个问题的方法就是在项目顶层pom.xml
文件中使用dependencyManagement
来声明那些可能用到的jar包以及其版本。子模块通过<parent>
标签来指定依赖顶层项目的pom
。子模块在写具体的dependencies
的时候,就可以不指定jar包的版本,默认会使用<parent>
中的dependencyManagement
中的版本,从而达到在一个项目中依赖的第三方jar包版本统一的目的。