Apache HttpClient API中的CloseableHttpClient和HttpClient有什么区别?


83

我正在研究由我们公司开发的应用程序。它使用Apache HttpClient库。在源代码中,它使用HttpClient该类来创建实例以连接到服务器。

我想了解Apache HttpClient,并且已经看过这组示例。所有示例均使用CloseableHttpClient代替HttpClient。所以我认为CloseableHttpClient是的扩展版本HttpClient。如果是这种情况,我有两个问题:

  • 两者有什么区别?
  • 建议为我的新开发使用哪个课程?

7
该文档对我来说似乎很清楚:“ HttpClient的基本实现也实现了Closeable”-HttpClient是一个接口;CloseableHttpClient是一个抽象类,但是由于它实现了AutoCloseable,因此您可以在try-with-resources语句中使用它。
乔恩·斯基特

3
@JonSkeet这很清楚,但是关闭HttpClient实例有多重要?如果重要,为什么该close()方法不属于基本接口?
Jules

3
@Jules:恐怕我对HttpClient的了解还不够多:(
Jon Skeet 2014年

关闭不需要成为基本接口的一部分,因为基础连接会自动释放回连接管理器
Jeril Kuruvila

Answers:


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

  • CloseableHttpClient是一个抽象类,它是HttpClient的基础实现,它也实现java.io.Closeable。
  • 这是最简单形式的请求执行过程示例:

    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpGet httpget =新的HttpGet(“ http:// localhost /”);
    CloseableHttpResponse响应= httpclient.execute(httpget);
    尝试{
        //做一点事
    }最后{
        response.close();
    }

  • HttpClient资源的释放:当不再需要实例CloseableHttpClient并且将要超出范围时,必须通过调用CloseableHttpClient#close()方法来关闭与其关联的连接管理器。

    CloseableHttpClient httpclient = HttpClients.createDefault();
    尝试{
        //做一点事
    }最后{
        httpclient.close();
    }

请参阅参考资料以学习基础知识。


@Scadge自Java 7起,使用try-with-resources语句可确保在语句末尾关闭每个资源。它可以用于客户端和每个响应

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
}

57
这个答案有点问题。在HttpClient上调用close()会导致什么发生,而这是不会发生的?如果您没有在适当的时间/地点调用close(),会泄漏连接吗?确实不需要时,调用close()是否会导致重新连接而过早地影响性能?
gilbertpilz

4
我浏览了httpclient中的代码,以找到该问题的答案。答案是close方法用于关闭内部状态。可以将HTTPClient的某些实现(位于httpclient lib中)配置为使用持久性资源(例如PooledHttpClientConnectionManager)进行池化连接,并且如果没有这种方法,您将无法在需要时清理这些资源。
Deadron

@SugarPudi在上面的例子中,我们需要关闭httpget
Kasun Siyambalapitiya

我们如何在这里调用抽象类(CloseableHttpClient)上的方法?我们不应该首先创建一个具体的子类吗?
illcar

@illcar请仔细研究这个答案以了解概念stackoverflow.com/a/4321402/2830834
Sagar Pudi

26

有同样的问题。其他答案似乎没有解决为什么close()确实是必要的?而且,Op似乎在努力寻找与HttpClient等一起使用的首选方式。


根据Apache的说法:

// 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.

另外,关系如下:

HttpClient (接口)

实施者:

CloseableHttpClient -线程安全。

DefaultHttpClient-已弃用ThreadSafe BUT ,请HttpClientBuilder改用。

HttpClientBuilder-不是ThreadSafe,而是创建ThreadSafe CloseableHttpClient

  • 用于创建CUSTOM CloseableHttpClient

HttpClients-不是ThreadSafe,而是创建ThreadSafe CloseableHttpClient

  • 用于创建默认或最小 CloseableHttpClient

根据Apache的首选方式:

CloseableHttpClient httpclient = HttpClients.createDefault();

这个例子他们httpclient.close()finally子句中给出也可以使用ResponseHandler


另外,mkyong的执行方式也很有趣:

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

他没有显示client.close()电话,但我认为有必要,因为client它仍然是的实例CloseableHttpClient


15

其他答案似乎没有解决为什么close()真正必要的问题?* 2

对答案“ HttpClient资源释放”有疑问。

在旧的3.x httpcomponents doc中提到了该文档,该文档很早就与4.x HC有很多区别。此外,解释如此简短,以至于没有说明该基础资源是什么。

我对4.5.2发布的源代码进行了一些研究,发现CloseableHttpClient:close()基本上只关闭其连接管理器的实现。

(FYI)这就是为什么当您使用共享PoolingClientConnectionManager并呼叫客户端时close()java.lang.IllegalStateException: Connection pool shut down会发生异常。为了避免,setConnectionManagerShared工作。

我宁愿去做CloseableHttpClient:close()在每次请求后

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

实际上,我还在库clj-http中找到了,它根本没有调用Apache HC 4.5上的Clojure包装器close()request在文件core.clj中查看func


1
您能否阐明为什么它比使用setConnectionManagerShared并在每次请求后都调用close()更好?
zyfo2

9

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


8

HttpClient不是类,而是接口。您不能按照您的意思将其用于开发。

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


2

CloseableHttpClient是httpclient库的基类,所有实现都使用它。其他子类在大多数情况下已被弃用。

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

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

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


0

乔恩·斯凯特(Jon skeet)说:

该文档对我来说似乎很清楚:“ HttpClient的基本实现也实现了Closeable”-HttpClient是一个接口;CloseableHttpClient是一个抽象类,但是由于它实现了AutoCloseable,因此您可以在try-with-resources语句中使用它。

但是朱尔斯问:

@JonSkeet这很清楚,但是关闭HttpClient实例有多重要?如果很重要,为什么close()方法不属于基本接口?

回答朱尔斯

close不必是基本接口的一部分,因为在每次执行后,基础连接会自动释放回连接管理器

容纳try-with-resources语句。必须实施Closeable。因此将其包含在CloseableHttpClient中

注意:

不推荐使用AbstractHttpClient中的close方法扩展CloseableHttpClient,我无法找到它的源代码。


这似乎仍未回答“关闭HttpClient实例有多重要?”
Vivek Chavda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.