What is the difference between CloseableHttpClient and HttpClient in Apache HttpClient API?

I'm studying an application developed by our company. It uses the Apache HttpClient library. In the source code it uses the HttpClient class to create instances to connect to a server.

I want to learn about Apache HttpClient and I've gone trough this set of examples. All the examples use CloseableHttpClient instead of HttpClient. So I think CloseableHttpClient is an extended version of HttpClient. If this is the case I have two questions:

  • What is the difference between these two?
  • Which class is recommended to use for my new development?
172723 次浏览

HttpClient不是一个类,它是一个接口。您不能按照您的意思使用它进行开发。

您需要的是一个实现 HttpClient接口的类,即 CloseableHttpClient

在下一个主要版本的库 HttpClient接口将扩展 Closeable。在此之前,如果不需要与早期的4.x 版本(4.0、4.1和4.2)兼容,建议使用 CloseableHttpClient

CloseableHttpClient是所有实现都使用的 httpclient 库的基类。其他子类在大多数情况下是不推荐的。

HttpClient是这个类和其他类的接口。

然后,您应该在代码中使用 CloseableHttpClient,并使用 HttpClientBuilder创建它。如果需要包装客户机以添加特定的行为,那么应该使用请求和响应拦截器,而不是使用 HttpClient包装。

这个答案是在 httpclient-4.3的上下文中给出的。

  • HttpClientAPI 的主要入口点是 HttpClient 接口。
  • HttpClient 最基本的功能是执行 HTTP 方法。
  • HTTP 方法的执行涉及一个或多个 HTTP 请求/HTTP 响应交换,通常由 HttpClient 在内部处理。

  • CloseableHttpClient 是一个抽象类,它是 HttpClient 的基本实现,也实现了 java.io.Closeable。
  • Here is an example of request execution process in its simplest form:

    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpGet httpget = new HttpGet("http://localhost/");
    CloseableHttpResponse response = httpclient.execute(httpget);
    try {
    //do something
    } finally {
    response.close();
    }

  • HttpClient resource deallocation: When an instance CloseableHttpClient is no longer needed and is about to go out of scope the connection manager associated with it must be shut down by calling the CloseableHttpClient#close() method.

    CloseableHttpClient httpclient = HttpClients.createDefault();
    try {
    //do something
    } finally {
    httpclient.close();
    }

see the Reference to learn fundamentals.


@Scadge Since Java 7, Use of try-with-resources statement ensures that each resource is closed at the end of the statement. It can be used both for the client and for each response

try(CloseableHttpClient httpclient = HttpClients.createDefault()){


// e.g. do this many times
try (CloseableHttpResponse response = httpclient.execute(httpget)) {
//do something
}


//do something else with httpclient here
}

Had the same question. The other answers don't seem to address why close() is really necessary? Also, Op seemed to be struggling to figure out the preferred way to work with HttpClient, et al.


根据 阿帕奇人:

// The underlying HTTP connection is still held by the response object
// to allow the response content to be streamed directly from the network socket.
// In order to ensure correct deallocation of system resources
// the user MUST call CloseableHttpResponse#close() from a finally clause.

In addition, the relationships go as follows:

HttpClient(接口)

执行机构包括:

线程安全。

线程安全但是 不赞成,使用 HttpClientBuilder代替。

不是 ThreadSafe,而是创建 ThreadSafe CloseableHttpClient

  • 用于创建自定义 CloseableHttpClient

HttpClients - NOT ThreadSafe, BUT creates ThreadSafe CloseableHttpClient.

  • 用于创建 DEFAULT 或 MINIMALCloseableHttpClient

按照 Apache 的说法,首选方法是:

CloseableHttpClient httpclient = HttpClients.createDefault();

他们给出的示例 finally子句中使用 httpclient.close(),并且也使用 ResponseHandler


作为另一种选择,mkyong 做这件事的方式也有点有趣:

HttpClient client = HttpClientBuilder.create().build();

He doesn't show a client.close() call but I would think it is necessary, since client is still an instance of CloseableHttpClient.

其他答案似乎没有解决为什么 close()是真正必要的

对“ HttpClient 资源回收”的疑问。

在旧的3.x httpComponent 医生中提到了这一点,它很早就出现了,与4.x HC 有很大的不同。此外,解释是如此简短,没有说明这个底层资源是什么。

I did some research on 4.5.2 release source code, found the implementations of CloseableHttpClient:close() basically only closes its connection manager.

(仅供参考)这就是为什么当您使用共享的 PoolingClientConnectionManager并调用客户端 close()时,会出现异常 java.lang.IllegalStateException: Connection pool shut down。为了避免,setConnectionManagerShared工作。

我喜欢 没有CloseableHttpClient:close()后,每一个请求

我过去常常在执行请求时创建一个新的 http 客户端实例,并最终关闭它。在这种情况下,最好不要调用 close()。因为,如果连接管理器没有“共享”标志,它将被关闭,这对于单个请求来说太昂贵了。

事实上,我还在库 你好中发现,一个基于 Apache HC 4.5的 Clojure 包装器根本不调用 close()。参见文件 Core.clj中的函数 request

乔恩•斯基特(Jon Skeet)表示:

文档对我来说非常清楚: “ HttpClient 的基本实现也实现了 Closeable”—— HttpClient 是一个接口; CloseableHttpClient 是一个抽象类,但是因为它实现了 AutoCloseable,所以你可以在 try-with-resources 语句中使用它。

但是朱尔斯问道:

@ JonSkeet 很明显,但是关闭 HttpClient 实例有多重要呢?如果它很重要,为什么 close ()方法不是基本接口的一部分?

回答 Jules 的问题

关闭不需要是基本接口的一部分,因为底层连接 在每次执行后自动释放回连接管理器

为了适应 try-with-resources 语句,必须实现 Closeable,因此将其包含在 CloseableHttpClient中。

注:

反对使用 AbstractHttpClient 中的 close 方法来扩展 CloseableHttpClient,因为我找不到这个方法的源代码。

你可以把 衣柜像这样放

final String uri = "http://localhost:8080/*****";
HttpGet httpGet = new HttpGet(uri);
try (final CloseableHttpClient httpClient = HttpClients.createDefault();
final CloseableHttpResponse response = httpClient.execute(httpGet)) {
final String result = EntityUtils.toString(response.getEntity());
...
} catch (Exception e) {
....
}