Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java HttpClient 4.0.1-如何释放连接?_Java_Connection_Apache Httpclient 4.x - Fatal编程技术网

Java HttpClient 4.0.1-如何释放连接?

Java HttpClient 4.0.1-如何释放连接?,java,connection,apache-httpclient-4.x,Java,Connection,Apache Httpclient 4.x,我在一堆URL上有一个循环,对于每一个URL,我都在执行以下操作: private String doQuery(String url) { HttpGet httpGet = new HttpGet(url); setDefaultHeaders(httpGet); // static method HttpResponse response = httpClient.execute(httpGet); // httpClient instantiated in constr

我在一堆URL上有一个循环,对于每一个URL,我都在执行以下操作:

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)


这只是一个简单的单线程应用程序。如何释放此连接?

要回答我自己的问题:要释放连接(以及与请求相关的任何其他资源),必须关闭HttpEntity返回的InputStream:

InputStream is = entity.getContent();

.... process the input stream ....

is.close();       // releases all resources

中,Httpcomponents 4.1推荐的方法是关闭连接并释放任何底层资源:

EntityUtils.consume(HttpEntity)
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
     } 
}

其中传递的
HttpEntity
是一个响应实体。

这似乎很有效:

      if( response.getEntity() != null ) {
         response.getEntity().consumeContent();
      }//if

即使您没有打开实体的内容,也不要忘记使用实体。例如,您期望从响应中获得HTTP_OK状态,但没有得到它,您仍然必须使用该实体

如果不使用响应,则可以使用以下代码中止请求:

// 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();
}
参考资料:


Apache HttpClient版本:4.1.3

自4.2版以来,他们引入了一种更方便的方法来简化连接发布:

我在多线程环境(servlet)中使用HttpClient时遇到了这个问题。 一个servlet仍然保持连接,另一个servlet希望获得连接

解决方案:

版本4.0使用
ThreadSafeClientConnManager

版本4.2使用池客户端连接管理器

设置这两个设置器:

setDefaultMaxPerRoute
setMaxTotal

HTTP头请求的处理方式必须略有不同,因为response.getEntity()为null。 相反,您必须捕获传递到HttpClient.execute()的HttpContext并检索连接参数以关闭它(无论如何,在HttpComponents 4.1.X中)


HttpComponents 4.2.X在HttpRequestBase中添加了一个releaseConnection(),以简化此操作。

我将提供一个详细的答案,专门针对Apache HttpClient 4.0.1。我正在使用这个HttpClient版本,因为它是由WAS v8.0提供的,我需要使用Apache Wink v1.1.1中提供的HttpClient(也是由WAS v8.0提供的),对Sharepoint进行一些NTLM验证的REST调用

要在Apache HttpClient邮件列表中引用Oleg Kalnichevski的话:

几乎所有这些代码都不是必需的。(1) HttpClient将 只要实体 内容被消耗到流的末尾;(2) HttpClient将 在任何I/O异常时自动释放基础连接 读取响应内容时引发。不需要特殊处理 在这种情况下需要

事实上,这完全足以确保适当释放资源:

EntityUtils.consume(HttpEntity)
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
     } 
}
就是这样


我遇到了同样的问题,通过在方法末尾关闭响应解决了这个问题:

try {
    // make the request and get the entity 
} catch(final Exception e) {
    // handle the exception
} finally {
    if(response != null) {
        response.close();
    }
}

我使用的是HttpClient 4.5.3,使用的是
CloseableHttpResponse#close
对我来说很有用

    CloseableHttpResponse response = client.execute(request);

    try {
        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        checkResult(body);
        EntityUtils.consume(entity);
    } finally {
        response.close();
    }
使用Java7及更高版本:

try (CloseableHttpResponse response = client.execute(request)) {
   ...
}

如果要重新使用连接,则必须在每次使用后完全使用内容流,如下所示:

EntityUtils.consume(response.getEntity())
注意:即使状态代码不是200,也需要使用内容流。不这样做会在下次使用时引发以下问题:

线程“main”java.lang.IllegalStateException中出现异常:SingleClientConnManager的使用无效:连接仍已分配。在分配另一个连接之前,请确保释放该连接


如果是一次性使用,那么只需关闭连接即可释放与之相关的所有资源

强烈建议使用处理程序来处理响应

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);
        }
    }
};
private ResponseHandler defaultHandler=new ResponseHandler(){
@凌驾
公共字符串句柄响应(HttpResponse响应)
抛出IOException{
int status=response.getStatusLine().getStatusCode();
如果(状态>=200&&status<300){
HttpEntity=response.getEntity();
返回实体!=null?EntityUtils.toString(实体):null;
}否则{
抛出新的ClientProtocolException(“意外响应状态:+状态”);
}
}
};

我不这么认为,我这样做了,我得到了“SingleClientConnManager的无效使用:连接仍然分配”。这可能是通过我可以从httpClient获得的ClientConnectionManager完成的,但它似乎不正确,我也是。你在重用httpClient吗?您如何确保它在请求失败时释放资源?我可以通过关闭InputStream来确认,我看到了调试消息:org.apache.http.impl.conn.BasicClientConnectionManager(18314):Releasing connectionI确认它工作正常。非常感谢。(顺便说一句,使用HttpComponents-4.1“EntityUtils.consume(httpEntity)”也可以完成这项工作)。Richard是对的,在接收到的输入流上调用“close()”,通知watcher关闭流,然后watcher关闭流本身并将连接标记为“可重用”(httpclient版本4.5.1)。这是4.1的正确答案。Richard H one的那个对我不起作用。我也面临着同样的问题。此解决方案有效,但并不涵盖所有可能的情况。我认为httpClient正在被重用。如果一些请求失败,正如您对HTTP所期望的那样,如何释放分配的资源还不清楚。即使遵循Apache提供的多个不同异常处理程序的示例,我仍然面临相同的问题:(@Rafael)您可以使用HttpRequestBa