HttpClient 4.0.1-연결 해제 방법?
여러 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) at org.apache.http.impl.conn.SingleClientConnManager $ 1.getConnection (SingleClientConnManager.java:173) ......
이것은 단순한 단일 스레드 앱입니다. 이 연결을 어떻게 해제 할 수 있습니까?
Httpcomponents 4.1에서 권장하는 방법은 연결을 닫고 기본 리소스를 해제하는 것입니다.
EntityUtils.consume(HttpEntity)
HttpEntity전달 된 곳 은 응답 엔터티입니다.
이것은 잘 작동하는 것 같습니다.
if( response.getEntity() != null ) {
response.getEntity().consumeContent();
}//if
그리고 콘텐츠를 열지 않았더라도 엔티티를 소비하는 것을 잊지 마십시오. 예를 들어, 응답에서 HTTP_OK 상태를 예상하고 얻지 못하더라도 여전히 엔티티를 소비해야합니다!
내 질문에 답하려면 연결 (및 요청과 관련된 다른 리소스)을 해제하려면 HttpEntity에서 반환 한 InputStream을 닫아야합니다.
InputStream is = entity.getContent();
.... process the input stream ....
is.close(); // releases all resources
로부터 문서
버전 4.2부터 연결 해제를 단순화하는 훨씬 더 편리한 메서드 인 HttpRequestBase.releaseConnection ()을 도입했습니다.
Apache HttpClient 4.0.1을 구체적으로 다루는 자세한 답변을 들었습니다. 이 HttpClient 버전은 WAS v8.0에서 제공하므로 WAS v8.0에서도 제공하는 Apache Wink v1.1.1 내에서 제공된 HttpClient를 사용하여 Sharepoint에 대한 NTLM 인증 REST 호출을 수행해야합니다. .
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 } }그게 다입니다.
응답을 사용하지 않을 경우 아래 코드를 사용하여 요청을 중단 할 수 있습니다.
// 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
다중 스레드 환경 (서블릿)에서 HttpClient를 사용할 때이 문제가 발생합니다. 한 서블릿은 여전히 연결을 유지하고 다른 서블릿은 연결을 원합니다.
해결책:
버전 4.0 사용 ThreadSafeClientConnManager
버전 4.2 사용 PoolingClientConnectionManager
이 두 setter를 설정합니다.
setDefaultMaxPerRoute
setMaxTotal
response.getEntity ()가 null이므로 HTTP HEAD 요청은 약간 다르게 처리되어야합니다. 대신 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 ()을 추가했습니다.
I'm using HttpClient 4.5.3, using CloseableHttpClient#close worked for me.
CloseableHttpResponse response = client.execute(request);
try {
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
checkResult(body);
EntityUtils.consume(entity);
} finally {
response.close();
}
If you want to re-use the connection then you must consume content stream completely after every use as follows :
EntityUtils.consume(response.getEntity())
Note : you need to consume the content stream even if the status code is not 200. Not doing so will raise the following on next use :
Exception in thread "main" java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
If it's a one time use, then simply closing the connection will release all the resources associated with it.
I had the same issue and solved it by closing the response at the end of the method:
try {
// make the request and get the entity
} catch(final Exception e) {
// handle the exception
} finally {
if(response != null) {
response.close();
}
}
Highly recommend using a handler to handle the response.
client.execute(yourRequest,defaultHanler);
It will release the connection automatically with consume(HTTPENTITY) method.
A handler example:
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);
}
}
};
참고URL : https://stackoverflow.com/questions/4775618/httpclient-4-0-1-how-to-release-connection
'developer tip' 카테고리의 다른 글
| 내 정렬 루프가하지 말아야 할 요소를 추가하는 것처럼 보이는 이유는 무엇입니까? (0) | 2020.10.31 |
|---|---|
| OnItemClickListener android를 사용한 ListView (0) | 2020.10.31 |
| 순서가 지정되지 않은 목록의 항목 뒤에 파이프 구분 기호 추가 (0) | 2020.10.31 |
| foreach 목록 항목의 역순 (0) | 2020.10.31 |
| LESS로 부트 스트랩 변수 재정의 (0) | 2020.10.31 |