httpclient与httpcore版本不匹配导致的编译问题

发布时间:2021年03月11日 阅读:3956 次

继上篇httpclient引入依赖冲突报错之后出现的问题,又出现错误

java.lang.NoSuchMethodError: org.apache.http.util.Args.containsNoBlanks(Ljava/lang/CharSequence;Ljava/lang/String;)Ljava/lang/CharSequence;
	at org.apache.http.HttpHost.<init>(HttpHost.java:80)
	at org.apache.http.client.utils.URIUtils.extractHost(URIUtils.java:370)
	at org.apache.http.impl.client.CloseableHttpClient.determineTarget(CloseableHttpClient.java:92)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)

依赖冲突是解决了,但是偶然性的出错

其实问题消失了不代表事情就可以结束了,原因是什么,为什么会出现这个问题? 做技术要有打破砂锅问到底的精神。

看项目中有很多文件有用到ThreadSafe这个注解,主要是有两个jar包,一个是httpclient, 一个是它自己所在的包httpcore。查看httpclient的pom.xml,写的也比较明确,httpclient会依赖于httpcore包.

<dependencies>
  <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <scope>compile</scope>
  </dependency>
  ....
 </dependencies>

image.png

groupIdartifactId比较容易理解,用于确定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包的版本进行统一管理,这个以后文章说明。META-INF/DEPENDENCIES文件如下

image.png


二、关于scope
我们在httpclient中看到了dependency的依赖范围是compile,这个scope还有哪些枚举值呢? 都代表什么意思? scope有6个枚举值, 分别如下

三、dependencies和dependencyManagement
要理解dependencyManagement需要知道它出现的背景,在一个多模块的工程中,各模块可能会依赖相同的jar包,之前是在每个模块的pom.xml中通过具体jar包的坐标来指定,但可能会造成不同版本之间jar包冲突导致的运行问题。
解决这个问题的方法就是在项目顶层pom.xml文件中使用dependencyManagement声明那些可能用到的jar包以及其版本。子模块通过<parent>标签来指定依赖顶层项目的pom。子模块在写具体的dependencies的时候,就可以不指定jar包的版本,默认会使用<parent>中的dependencyManagement中的版本,从而达到在一个项目中依赖的第三方jar包版本统一的目的。

四、dependency标签下参数

<dependency>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <type></type>
    <optional></optional>
    <scope></scope>
    <classifier></classifier>
    <systemPath></systemPath>
    <exclusions></exclusions>
</dependency>

基本的groupId、artifactId、version在这里就不介绍了。

4.1 type

有时候我们引入某一个依赖时,必须指定type这是因为用于匹配dependency引用和dependencyManagement部分的最小信息集实际上是{groupId,artifactId,type,classifier}。在很多情况下,这些依赖关系将引用没有classifier的jar依赖。这允许我们将标识设置为{groupId,artifactId},因为type的默认值是jar,并且默认classifiernull

type的值一般有jar、war、pom等,声明引入的依赖的类型。

4.2 classifier

Classifier可能是最容易被忽略的Maven特性,但它确实非常重要,我们也需要它来帮助规划坐标。设想这样一个情况,有一个jar项目,就说是 dog-cli-1.0.jar 吧,运行它用户就能在命令行上画一只小狗出来。现在用户的要求是希望你能提供一个zip包,里面不仅包含这个可运行的jar,还得包含源代码和文档,换句话说,这是比较正式的分发包。这个文件名应该是怎样的呢?dog-cli-1.0.zip?不够清楚,仅仅从扩展名很难分辨什么是Maven默认生成的构件,什么是额外配置生成分发包。如果能是dog-cli-1.0-dist.zip就最好了。这里的dist就是classifier,默认Maven只生成一个构件,我们称之为主构件,那当我们希望Maven生成其他附属构件的时候,就能用上classifier。常见的classifier还有如dog-cli-1.0-sources.jar表示源码包,dog-cli-1.0-javadoc.jar表示JavaDoc包等等。

classifier它表示在相同版本下针对不同的环境或者jdk使用的jar,如果配置了这个元素,则会将这个元素名在加在最后来查找相应的jar,例如:

上面的例子
<classifier>sources</classifier>
<classifier>javadoc</classifier>
给相同的version,构建不同的环境使用依赖
<classifier>jdk17</classifier>
<classifier>jdk18</classifier>

4.3 optional

当project-A 依赖project-B, project-B 依赖project-D时

<dependency>
  <groupId>sample.ProjectD</groupId>
  <artifactId>ProjectD</artifactId>
  <version>1.0-SNAPSHOT</version>
  <optional>true</optional>
</dependency>

所以当project-B的<optional>true</optional>时, project-A中如果没有显式的引入project-D, 则project-A不依赖project-D, 即project-A可以自己选择是否依赖project-D

默认<optional>的值为false, 及子项目必须依赖。

4.4 scope

上文讲到了,不再列出了

4.5 systemPath

当maven依赖本地而非repository中的jar包,sytemPath指明本地jar包路径,例如:

<dependency>
    <groupId>cn.ucloud.ufile</groupId>
    <artifactId>cn.ucloud.ufile</artifactId>
    <scope>system</scope>
    <version>0.1.1</version>
    <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ufile_sdk.jar</systemPath>
</dependency>

4.6 exclusions

依赖排除,就是有时候引入某一个依赖的时候,该依赖下有jar包冲突,可以排除掉,不引用该jar,例如:

<dependency>
   <groupId>cn.ucloud.ufile</groupId>
   <artifactId>cn.ucloud.ufile</artifactId>
   <scope>system</scope>
   <version>0.1.1</version>
   <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ufile_sdk.jar</systemPath>
   <exclusions>
      <exclusion>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
      </exclusion>
   </exclusions>
</dependency>
Tag:JAVA 导致NoSuchMethodError问题 httpclient依赖冲突 mavaen依赖关系
相关文章