我对一堆网址进行了循环,对于每一个我正在执行以下操作的网址:
private String doQuery(String url) {
HttpGet httpGet = new HttpGet(url);
setDefaultHeaders(httpGet); // static method
HttpResponse response = httpClient.execute(httpGet); // httpClient instantiated in constructor
int rc = response.getStatusLine().getStatusCode();
if (rc != 200) {
// some stuff...
return;
}
HttpEntity entity = response.getEntity();
if (entity == null) {
// some stuff...
return;
}
// process the entity, get input stream etc
}
第一个查询没问题,第二个查询抛出此异常:
线程“main”中的异常 java.lang.IllegalStateException: 使用无效 SingleClientConnManager:连接 仍然分配。一定要发布 分配前的连接 另一个。在 org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:199) 在 org.apache.http.impl.conn.SingleClientConnManager $ 1.getConnection(SingleClientConnManager.java:173)......
这只是一个简单的单线程应用程序。我该如何发布此连接?
答案 0 :(得分:94)
Httpcomponents 4.1推荐的方法是关闭连接并释放任何底层资源:
EntityUtils.consume(HttpEntity)
其中HttpEntity
传递的是响应实体。
答案 1 :(得分:31)
这似乎很有效:
if( response.getEntity() != null ) {
response.getEntity().consumeContent();
}//if
即使您没有打开其内容,也不要忘记使用该实体。例如,您希望响应中的HTTP_OK状态并且没有得到它,您仍然必须使用该实体!
答案 2 :(得分:22)
回答我自己的问题:要释放连接(以及与请求关联的任何其他资源),您必须关闭HttpEntity返回的InputStream:
InputStream is = entity.getContent();
.... process the input stream ....
is.close(); // releases all resources
来自docs
答案 3 :(得分:18)
从版本4.2开始,他们引入了一种更简便的方法来简化连接释放:HttpRequestBase.releaseConnection()
答案 4 :(得分:12)
我正在寻找专门针对Apache HttpClient 4.0.1的详细解答。我正在使用这个HttpClient版本,因为它是由WAS v8.0提供的,我需要在Apache Wink v1.1.1中使用提供的HttpClient(也是由WAS v8.0提供)来制作一些NTLM -authenticated REST调用Sharepoint。
在Apache HttpClient邮件列表上引用Oleg Kalnichevski:
几乎所有这些代码都没有必要。 (1)HttpClient会 只要实体自动释放底层连接 内容被消耗到流的末尾; (2)HttpClient会 在任何I / O异常上自动释放底层连接 在阅读响应内容时抛出。没有特殊处理 在这种情况下需要。
事实上,这足以确保正确释放资源:
HttpResponse rsp = httpclient.execute(target, req); HttpEntity entity = rsp.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); try { // process content } finally { instream.close(); // entity.consumeContent() would also do } }
就是这样。
答案 5 :(得分:7)
如果不消耗响应,则可以使用以下代码中止请求:
// Low level resources should be released before initiating a new request
HttpEntity entity = response.getEntity();
if (entity != null) {
// Do not need the rest
httpPost.abort();
}
参考:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e143
Apache HttpClient版本:4.1.3
答案 6 :(得分:4)
当我在多线程环境(Servlets)中使用HttpClient时,我遇到了这个问题。 一个servlet仍然保持连接,另一个servlet想要连接。
解决方案:
版本4.0使用ThreadSafeClientConnManager
版本4.2使用PoolingClientConnectionManager
并设置这两个二传手:
setDefaultMaxPerRoute
setMaxTotal
答案 7 :(得分:2)
HTTP HEAD请求的处理方式必须略有不同,因为response.getEntity()为null。 相反,您必须捕获传递给HttpClient.execute()的HttpContext并检索连接参数以关闭它(无论如何在HttpComponents 4.1.X中)。
HttpRequest httpRqst = new HttpHead( uri );
HttpContext httpContext = httpFactory.createContext();
HttpResponse httpResp = httpClient.execute( httpRqst, httpContext );
...
// Close when finished
HttpEntity entity = httpResp.getEntity();
if( null != entity )
// Handles standard 'GET' case
EntityUtils.consume( entity );
else {
ConnectionReleaseTrigger conn =
(ConnectionReleaseTrigger) httpContext.getAttribute( ExecutionContext.HTTP_CONNECTION );
// Handles 'HEAD' where entity is not returned
if( null != conn )
conn.releaseConnection();
}
HttpComponents 4.2.X为HttpRequestBase添加了一个releaseConnection()以使其更容易。
答案 8 :(得分:1)
我正在使用HttpClient 4.5.3,使用$('input').on('ifChanged', function(event) {
if($(".checkbox").is(":checked")) {
$value = $(this).val();
}
else if($(".checkbox").is(":not(:checked)")) {
$value= $(this).val();
}
});
为我工作。
CloseableHttpClient#close
答案 9 :(得分:1)
如果要重新使用连接,则必须在每次使用后完全使用内容流,如下所示:
EntityUtils.consume(response.getEntity())
注意:即使状态代码不是200,您也需要使用内容流。不这样做会在下次使用时引发以下内容:
线程中的异常" main" java.lang.IllegalStateException:无效使用SingleClientConnManager:仍然分配了连接。确保在分配另一个连接之前释放连接。
如果它是一次性使用,那么只需关闭连接就会释放与之关联的所有资源。
答案 10 :(得分:0)
我遇到了同样的问题,并通过在方法结束时关闭响应来解决它:
try {
// make the request and get the entity
} catch(final Exception e) {
// handle the exception
} finally {
if(response != null) {
response.close();
}
}
答案 11 :(得分:0)
强烈建议使用处理程序来处理响应。
client.execute(yourRequest,defaultHanler);
它将使用consume(HTTPENTITY)
方法自动释放连接。
处理程序示例:
private ResponseHandler<String> defaultHandler = new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse response)
throws IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
} else {
throw new ClientProtocolException("Unexpected response status: " + status);
}
}
};