HttpClient
类创建实例来连接服务器。我想学习Apache HttpClient,并且已经浏览了这个示例集。所有示例都使用
CloseableHttpClient
而不是HttpClient
。因此,我认为CloseableHttpClient
是HttpClient
的扩展版本。如果是这样,我有两个问题:
- 这两者之间有什么区别?
- 哪个类建议在我的新开发中使用?
HttpClient
类创建实例来连接服务器。CloseableHttpClient
而不是HttpClient
。因此,我认为CloseableHttpClient
是HttpClient
的扩展版本。如果是这样,我有两个问题:
以下是其最简单形式的请求执行过程示例:
CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet httpget = new HttpGet("http://localhost/"); CloseableHttpResponse response = httpclient.execute(httpget); try { //做些什么 } finally { response.close(); }
HttpClient资源释放: 当CloseableHttpClient实例不再需要并且即将超出范围时,必须通过调用CloseableHttpClient#close()方法来关闭与之关联的连接管理器。
CloseableHttpClient httpclient = HttpClients.createDefault(); try { //do something } finally { 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
}
我有同样的问题。其他答案似乎没有解释为什么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
- 线程安全但已弃用,请使用HttpClientBuilder
代替。
HttpClientBuilder
- 非线程安全,但可创建线程安全的CloseableHttpClient
。
- 用于创建自定义
CloseableHttpClient
。
HttpClients
- 非线程安全,但可创建线程安全的CloseableHttpClient
。
- 用于创建默认或最小化
CloseableHttpClient
。
根据Apache的建议,首选方式为:
CloseableHttpClient httpclient = HttpClients.createDefault();
他们提供的示例在finally
子句中执行httpclient.close()
,同时还使用了ResponseHandler
。作为一种替代方法,mkyong的做法也很有趣:HttpClient client = HttpClientBuilder.create().build();
他没有展示client.close()
的调用,但我认为这是必要的,因为client
仍然是CloseableHttpClient
类的一个实例。
他没有展示client.close()
的调用,但我认为这是必要的,因为client
仍然是CloseableHttpClient
类的一个实例。
HttpClientBuilder.create().build();
是 HttpClients.createDefault();
底层使用的,因此不应该有任何区别。 - SirHawrk其他答案似乎没有解释为什么close()
真的是必要的? * 2
它在旧版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()
close()
。因为,如果连接管理器没有“共享”标志,它将被关闭,这对于单个请求来说太昂贵了。close()
。请参见文件core.clj中的函数request
。HttpClient
不是一个类,它是一个接口。你不能像你想的那样使用它进行开发。
你需要的是实现 HttpClient
接口的类,即 CloseableHttpClient
。
HttpClient
接口将扩展Closeable
。在那之前,建议使用CloseableHttpClient
,如果不需要与早期的4.x版本(4.0、4.1和4.2)兼容性。CloseableHttpClient
是 httpclient 库的基类,所有实现都使用它。其他子类大部分已经过时。
HttpClient
是这个类和其他类的接口。
在你的代码中应该使用 CloseableHttpClient
,并使用 HttpClientBuilder
创建它。如果你需要包装客户端以添加特定行为,你应该使用请求和响应拦截器,而不是用 HttpClient
包装。
此答案是针对 httpclient-4.3 的上下文给出的。
Jon Skeet说:
文档对我来说很清楚:“HttpClient的基本实现,同时也实现了Closeable”- HttpClient是一个接口;CloseableHttpClient是一个抽象类,但由于它实现了AutoCloseable,因此您可以在try-with-resources语句中使用它。
然后Jules问道:
@JonSkeet 那么关闭HttpClient实例有多重要?如果很重要,为什么close()方法不是基本接口的一部分?
Jules的答案
由于每次执行后底层连接都会自动释放回连接管理器,因此close不需要成为基本接口的一部分。
为了适应try-with-resources语句,必须实现Closeable。因此将其包含在CloseableHttpClient中。
注意:
AbstractHttpClient中的close方法已被弃用,它扩展了CloseableHttpClient,但我找不到该源代码。
您可以像这样放置Closeables
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) {
....
}
HttpClient
实例有多重要呢?如果很重要,为什么close()
方法不是基本接口的一部分呢? - Jules