httpclient的使用(二)

一、HTTP context的使用


 

HTTP协议是无状态的协议,但是在使用时,我们总希望一些状态信息能够更长的时间,我们称之为上下文。我们可以采用以下方式为我们的会话增加状态信息。

1 HttpContext httpContext = new BasicHttpContext();
2 HttpGet httpGet = <...>
3 HttpResponse response = httpClient.execute(httpGet, httpContext);

HttpClient提供了一下属性可以添加到我们中会话中,这是属性以键值对的方式存在于context中

  • HttpConnection
  • HttpHost
  • HttpRoute
  • HttpRequest
  • HttpResponse
  • java.lang.Boolean
  • RequestConfig
  • java.util.List<URI>

下面的代码是增加RequestConfig属性

 1 CloseableHttpClient httpclient = HttpClients.createDefault();
 2 RequestConfig requestConfig = RequestConfig.custom()
 3         .setSocketTimeout(1000)
 4         .setConnectTimeout(1000)
 5         .build();
 6 HttpGet httpget1 = new HttpGet("http://localhost/1");
 7 httpget1.setConfig(requestConfig);
 8 CloseableHttpResponse response1 = httpclient.execute(httpget1, context);
 9 try {
10     HttpEntity entity1 = response1.getEntity();
11 } finally {
12     response1.close();
13 }
14 HttpGet httpget2 = new HttpGet("http://localhost/2");
15 CloseableHttpResponse response2 = httpclient.execute(httpget2, context);
16 try {
17     HttpEntity entity2 = response2.getEntity();
18 } finally {
19     response2.close();
20 }

context测试样例

 1 package download.test;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.http.HttpEntity;
 6 import org.apache.http.HttpHost;
 7 import org.apache.http.HttpResponse;
 8 import org.apache.http.client.ClientProtocolException;
 9 import org.apache.http.client.methods.HttpGet;
10 import org.apache.http.client.methods.HttpUriRequest;
11 import org.apache.http.client.protocol.HttpClientContext;
12 import org.apache.http.entity.ContentType;
13 import org.apache.http.impl.client.CloseableHttpClient;
14 import org.apache.http.impl.client.HttpClients;
15 import org.apache.http.protocol.BasicHttpContext;
16 import org.apache.http.protocol.HttpContext;
17 import org.apache.http.util.EntityUtils;
18 
19 public class Download {
20 
21     public static void main(String[] args) throws ClientProtocolException,
22             IOException {
23         /**
24          * 获取重定向之后的网址信息
25          * 
26          * @see HttpClient缺省会自动处理客户端重定向
27          * @see 即访问网页A后,假设被重定向到了B网页,那么HttpClient将自动返回B网页的内容
28          * @see 若想取得B网页的地址
29          *      ,就需要借助HttpContext对象,HttpContext实际上是客户端用来在多次请求响应的交互中,保持状态信息的
30          * @see 我们自己也可以利用HttpContext来存放一些我们需要的信息,以便下次请求的时候能够取出这些信息来使用
31          */
32 
33         CloseableHttpClient httpClient = HttpClients.createDefault();
34         HttpContext httpContext = new BasicHttpContext();
35         HttpGet httpGet = new HttpGet("http://127.0.0.1:80/");
36         try {
37             // 将HttpContext对象作为参数传给execute()方法,则HttpClient会把请求响应交互过程中的状态信息存储在HttpContext中
38             HttpResponse response = httpClient.execute(httpGet, httpContext);
39             // 将httpContext放入到适配器中以方便访问
40             HttpClientContext clientContext = HttpClientContext
41                     .adapt(httpContext);
42             HttpHost targetHost = clientContext.getTargetHost();
43             // 获取实际的请求对象的URI
44             HttpUriRequest realRequest = (HttpUriRequest) clientContext.getRequest();
45             // .getRequest();
46             System.out.println("主机地址:" + targetHost);
47             System.out.println("URI信息:" + realRequest.getURI());
48             HttpEntity entity = response.getEntity();
49             if (null != entity) {
50                 System.out.println("响应内容:"
51                         + EntityUtils.toString(entity, ContentType
52                                 .getOrDefault(entity).getCharset()));
53                 EntityUtils.consume(entity);
54             }
55         } catch (Exception e) {
56             e.printStackTrace();
57         } finally {
58             httpClient.close();;
59         }
60     }
61 }

二、HTTP拦截器的使用


 HTTP拦截器可以对特定的请求、应答甚至页面进行处理,也能通过HTTP上下文环境进行信息共享,如果多个拦截器协同工作时要考虑执行顺序的问题。

下面的例子是将本地context的信息添加到所有的请求头中

 1 CloseableHttpClient httpclient = HttpClients.custom()
 2         .addInterceptorLast(new HttpRequestInterceptor() {
 3             public void process(
 4                     final HttpRequest request,
 5                     final HttpContext context) throws HttpException, IOException {
 6                 AtomicInteger count = (AtomicInteger) context.getAttribute("count");
 7                 request.addHeader("Count", Integer.toString(count.getAndIncrement()));
 8             }
 9         })
10         .build();
11 AtomicInteger count = new AtomicInteger(1);
12 HttpClientContext localContext = HttpClientContext.create();
13 localContext.setAttribute("count", count);
14 HttpGet httpget = new HttpGet("http://localhost/");
15 for (int i = 0; i < 10; i++) {
16     CloseableHttpResponse response = httpclient.execute(httpget, localContext);
17     try {
18         HttpEntity entity = response.getEntity();
19     } finally {
20         response.close();
21     }
22 }

 三、请求retry操作


 

在发起http请求时可能因为网络拥塞等原因,使得发送失败,这时我们会尝试重新发送请求。

 1 HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
 2     public boolean retryRequest(
 3             IOException exception,
 4             int executionCount,
 5             HttpContext context) {
 6         if (executionCount >= 5) {
 7             // Do not retry if over max retry count
 8             return false;
 9         }
10         if (exception instanceof InterruptedIOException) {
11             // Timeout
12             return false;
13         }
14         if (exception instanceof UnknownHostException) {
15             // Unknown host
16             return false;
17         }
18         if (exception instanceof ConnectTimeoutException) {
19             // Connection refused
20             return false;
21         }
22         if (exception instanceof SSLException) {
23             // SSL handshake exception
24             return false;
25         }
26         HttpClientContext clientContext =         HttpClientContext.adapt(context);
27         HttpRequest request = clientContext.getRequest();
28         boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
29         if (idempotent) {
30             // Retry if the request is considered idempotent
31             return true;
32         }
33         return false;
34     }
35 };
36 CloseableHttpClient httpclient = HttpClients.custom()
37         .setRetryHandler(myRetryHandler)
38         .build();

 

posted @ 2016-02-24 20:31 被罚站的树 阅读(...) 评论(...)  编辑 收藏