本文主要研究一下HttpClient的ResponseHandler
org/apache/http/client/ResponseHandler.java
public interface ResponseHandler {
/**
* Processes an {@link HttpResponse} and returns some value
* corresponding to that response.
*
* @param response The response to process
* @return A value determined by the response
*
* @throws ClientProtocolException in case of an http protocol error
* @throws IOException in case of a problem or the connection was aborted
*/
T handleResponse(HttpResponse response) throws ClientProtocolException, IOException;
}
ResponseHandler定义了handleResponse方法,用于解析HttpResponse到泛型T
org/apache/http/impl/client/AbstractResponseHandler.java
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public abstract class AbstractResponseHandler implements ResponseHandler {
/**
* Read the entity from the response body and pass it to the entity handler
* method if the response was successful (a 2xx status code). If no response
* body exists, this returns null. If the response was unsuccessful (>= 300
* status code), throws an {@link HttpResponseException}.
*/
@Override
public T handleResponse(final HttpResponse response)
throws HttpResponseException, IOException {
final StatusLine statusLine = response.getStatusLine();
final HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
EntityUtils.consume(entity);
throw new HttpResponseException(statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
return entity == null ? null : handleEntity(entity);
}
/**
* Handle the response entity and transform it into the actual response
* object.
*/
public abstract T handleEntity(HttpEntity entity) throws IOException;
}
AbstractResponseHandler声明实现ResponseHandler接口,其handleResponse方法针对statusCode大于等于300的抛出HttpResponseException,对于entity不为null的执行handleEntity方法
org/apache/http/impl/client/BasicResponseHandler.java
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class BasicResponseHandler extends AbstractResponseHandler {
/**
* Returns the entity as a body as a String.
*/
@Override
public String handleEntity(final HttpEntity entity) throws IOException {
return EntityUtils.toString(entity);
}
@Override
public String handleResponse(
final HttpResponse response) throws HttpResponseException, IOException {
return super.handleResponse(response);
}
}
BasicResponseHandler继承了AbstractResponseHandler,它将entity转为String,使用的是EntityUtils.toString(entity)方法
org/apache/http/util/EntityUtils.java
public static String toString(final HttpEntity entity) throws IOException, ParseException {
Args.notNull(entity, "Entity");
return toString(entity, ContentType.get(entity));
}
private static String toString(
final HttpEntity entity,
final ContentType contentType) throws IOException {
final InputStream inStream = entity.getContent();
if (inStream == null) {
return null;
}
try {
Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
"HTTP entity too large to be buffered in memory");
int capacity = (int)entity.getContentLength();
if (capacity < 0) {
capacity = DEFAULT_BUFFER_SIZE;
}
Charset charset = null;
if (contentType != null) {
charset = contentType.getCharset();
if (charset == null) {
final ContentType defaultContentType = ContentType.getByMimeType(contentType.getMimeType());
charset = defaultContentType != null ? defaultContentType.getCharset() : null;
}
}
if (charset == null) {
charset = HTTP.DEF_CONTENT_CHARSET;
}
final Reader reader = new InputStreamReader(inStream, charset);
final CharArrayBuffer buffer = new CharArrayBuffer(capacity);
final char[] tmp = new char[1024];
int l;
while((l = reader.read(tmp)) != -1) {
buffer.append(tmp, 0, l);
}
return buffer.toString();
} finally {
inStream.close();
}
}
EntityUtils.toString方法通过entity.getContent()获取InputStream,之后将InputStream读取到CharArrayBuffer,最后关闭InputStream
org/apache/http/impl/client/CloseableHttpClient.java
@Override
public T execute(final HttpHost target, final HttpRequest request,
final ResponseHandler extends T> responseHandler, final HttpContext context)
throws IOException, ClientProtocolException {
Args.notNull(responseHandler, "Response handler");
final CloseableHttpResponse response = execute(target, request, context);
try {
final T result = responseHandler.handleResponse(response);
final HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
return result;
} catch (final ClientProtocolException t) {
// Try to salvage the underlying connection in case of a protocol exception
final HttpEntity entity = response.getEntity();
try {
EntityUtils.consume(entity);
} catch (final Exception t2) {
// Log this exception. The original exception is more
// important and will be thrown to the caller.
this.log.warn("Error consuming content after an exception.", t2);
}
throw t;
} finally {
response.close();
}
}
CloseableHttpClient的execute方法先执行execute,然后try catch执行responseHandler.handleResponse,然后执行EntityUtils.consume(entity),在ClientProtocolException的时候也会执行EntityUtils.consume(entity),最后执行response.close()
HttpClient提供了ResponseHandler接口,它有一个实现类是BasicResponseHandler,将entity的content转为string;相应的CloseableHttpClient也提供了支持ResponseHandler参数的execute方法,它先执行无handler的execute方法,然后try catch执行responseHandler.handleResponse,然后执行EntityUtils.consume(entity),在ClientProtocolException的时候也会执行EntityUtils.consume(entity),最后执行response.close()。