Httpclient4.4之原理(Http执行上下文)
最初HTTP被设计为无状态的。然而,真实的应用中常常要能够通过几个逻辑相关的请求/响应保持状态信息。为了使应用程序能够保持一个处理状态,HttpClient允许HTTP请求在特定的执行上下文内执行,称为HTTP上下文。如果相同的上下文在连续的请求之间重用,多个逻辑相关的连续请求可以参与一个逻辑会话。HTTP上下文的功能类似于java.util.Map<String,Object>,它只不过是任意命名的值的集合。应用程序能在请求执行之前填充上下文属性,也能在请求执行完成之后检查上下文。
HttpContext能包含任意对象,因此,可能不是线程安全的。建议每个执行线程维护自己的上下文。
在HTTP请求执行的过程中,HttpClient添加以下属性到执行上下文:
- HttpConnection:它代表连接到目标服务器的实际连接。
- HttpHost:它代表连接目标。
- HttpRoute:它代表一个完整的连接路由。
- HttpRequest:它代表一个真实的HTTP请求。在上下文中的最后的HttpRequest对象总是代表一个精确的消息状态被发送到目标服务器。默认的HTTP1.0和HTTP1.1使用相对的请求URI,然而请求是在非隧道模式中通过代理发送的,那么它是绝对URI。
- HttpResponse:它代表当前的HTTP响应。
- java.lang.Boolean:它代表一个标志,标识当前请求是否已经被完全传送到连接目标。
- RequestConfig:它代表当前请求的配置。
- java.util.List:它代表在请求执行过程中接收到的所有重定向地址的集合。
我们可以使用HttpClientContext适配器类来简化与上下文状态之间的相互作用:
HttpContext context = <...>
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpHost target = clientContext.getTargetHost();
HttpRequest request = clientContext.getRequest();
HttpResponse response = clientContext.getResponse();
RequestConfig config = clientContext.getRequestConfig();
代表一个逻辑相关会话的多请求序列应执行在同一个HttpContext实体中,确保会话上下文与状态信息在请求间自动传播(示例衔接上面的示例):
CloseableHttpClient httpclient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().
setSocketTimeout(1000).setConnectTimeout(1000).build();
HttpGet httpget1 = new HttpGet("http://localhost/1");
httpget1.setConfig(requestConfig);
//context上个示例中定义了
CloseableHttpResponse response1 = httpclient.execute(httpget1, context);
try {
HttpEntity entity1 = response1.getEntity();
} finally {
response1.close();
}
HttpGet httpget2 = new HttpGet("http://localhost/2");
CloseableHttpResponse response2 = httpclient.execute(httpget2, context);
try {
HttpEntity entity2 = response2.getEntity();
} finally {
response2.close();
}