使用Apache HttpClient 4.x进行异常重试

在进行http请求时,难免会遇到请求失败的情况,失败后需要重新请求,尝试再次获取数据。

Apache的HttpClient提供了异常重试机制,在该机制中,我们可以很灵活的定义在哪些异常情况下进行重试。

重试前提

被请求的方法必须是幂等的:就是多次请求服务端结果应该是准确且一致的。

适合的方法:比如根据ID,修改人员姓名,无论请求多次结果都是一样,这就是幂等。

不适合的方法:比如减少账号50元,多次请求将多次扣减。

实现方式

想要实现异常重试,需要实现它提供的一个接口  HttpRequestRetryHandler ,并实现 retryRequest 方法。然后set到HttpClient中。该httpClient就具备了重试机制。

HttpClient自身提供了 StandardHttpRequestRetryHandler 和 DefaultHttpRequestRetryHandler 两个实现类。 DefaultHttpRequestRetryHandler 继承自 DefaultHttpRequestRetryHandler , StandardHttpRequestRetryHandler 默认几个方法为幂等,如PUT、GET、HEAD等除POST外的方法,如果自定义可以参考它的实现方式。

代码如下:

  1 import java.io.IOException;
  2 import java.io.InterruptedIOException;
  3 import java.net.ConnectException;
  4 import java.net.UnknownHostException;
  5
  6 import javax.net.ssl.SSLException;
  7
  8 import org.apache.commons.lang3.ObjectUtils;
  9 import org.apache.commons.lang3.StringUtils;
 10 import org.apache.http.Consts;
 11 import org.apache.http.HttpEntityEnclosingRequest;
 12 import org.apache.http.HttpRequest;
 13 import org.apache.http.HttpStatus;
 14 import org.apache.http.ParseException;
 15 import org.apache.http.client.HttpRequestRetryHandler;
 16 import org.apache.http.client.config.RequestConfig;
 17 import org.apache.http.client.methods.CloseableHttpResponse;
 18 import org.apache.http.client.methods.HttpPost;
 19 import org.apache.http.client.protocol.HttpClientContext;
 20 import org.apache.http.entity.ContentType;
 21 import org.apache.http.entity.StringEntity;
 22 import org.apache.http.impl.client.CloseableHttpClient;
 23 import org.apache.http.impl.client.HttpClients;
 24 import org.apache.http.protocol.HttpContext;
 25 import org.apache.http.util.EntityUtils;
 26
 27 /**
 28  * @author 29  *
 29  * @date 2017年5月18日 上午9:17:30
 30  *
 31  * @Description
 32  */
 33 public class HttpPostUtils {
 34     /**
 35      *
 36      * @param uri
 37      *            the request address
 38      * @param json
 39      *            the request data that must be a JSON string
 40      * @param retryCount
 41      *            the number of times this method has been unsuccessfully
 42      *            executed
 43      * @param connectTimeout
 44      *            the timeout in milliseconds until a connection is established
 45      * @param connectionRequestTimeout
 46      *            the timeout in milliseconds used when requesting a connection
 47      *            from the connection manager
 48      * @param socketTimeout
 49      *            the socket timeout in milliseconds, which is the timeout for
 50      *            waiting for data or, put differently, a maximum period
 51      *            inactivity between two consecutive data packets
 52      * @return null when method parameter is null, "", " "
 53      * @throws IOException
 54      *             if HTTP connection can not opened or closed successfully
 55      * @throws ParseException
 56      *             if response data can not be parsed successfully
 57      */
 58     public String retryPostJson(String uri, String json, int retryCount, int connectTimeout,
 59             int connectionRequestTimeout, int socketTimeout) throws IOException, ParseException {
 60         if (StringUtils.isAnyBlank(uri, json)) {
 61             return null;
 62         }
 63
 64         HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
 65
 66             @Override
 67             public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
 68                 if (executionCount > retryCount) {
 69                     // Do not retry if over max retry count
 70                     return false;
 71                 }
 72                 if (exception instanceof InterruptedIOException) {
 73                     // An input or output transfer has been terminated
 74                     return false;
 75                 }
 76                 if (exception instanceof UnknownHostException) {
 77                     // Unknown host 修改代码让不识别主机时重试,实际业务当不识别的时候不应该重试,再次为了演示重试过程,执行会显示retryCount次下面的输出
 78                     System.out.println("不识别主机重试"); return true;
 79                 }
 80                 if (exception instanceof ConnectException) {
 81                     // Connection refused
 82                     return false;
 83                 }
 84                 if (exception instanceof SSLException) {
 85                     // SSL handshake exception
 86                     return false;
 87                 }
 88                 HttpClientContext clientContext = HttpClientContext.adapt(context);
 89                 HttpRequest request = clientContext.getRequest();
 90                 boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
 91                 if (idempotent) {
 92                     // Retry if the request is considered idempotent
 93                     return true;
 94                 }
 95                 return false;
 96             }
 97         };
 98
 99         CloseableHttpClient client = HttpClients.custom().setRetryHandler(httpRequestRetryHandler).build();
100         HttpPost post = new HttpPost(uri);
101         // Create request data
102         StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
103         // Set request body
104         post.setEntity(entity);
105
106         RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout)
107                 .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build();
108         post.setConfig(config);
109         // Response content
110         String responseContent = null;
111         CloseableHttpResponse response = null;
112         try {
113             response = client.execute(post, HttpClientContext.create());
114             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
115                 responseContent = EntityUtils.toString(response.getEntity(), Consts.UTF_8.name());
116             }
117         } finally {
118             if (ObjectUtils.anyNotNull(response)) {
119                 response.close();
120             }
121             if (ObjectUtils.anyNotNull(client)) {
122                 client.close();
123             }
124         }
125         return responseContent;
126     }

转载自:http://www.cnblogs.com/wuxiaofeng/p/6879292.html,感谢分享。

时间: 2024-08-27 09:51:07

使用Apache HttpClient 4.x进行异常重试的相关文章

Apache HttpClient : Http Cookies

前言 HttpClient已经被集成到Android的SDK里,但在JDK里面仍然需要HttpURLConnectionn发起HTTP请求.HttpClient可以看做是一个加强版的HttpURLConnection,但它的侧重点是如何发送请求.接受相应和管理Http连接. 在介绍Http Cookies之前,笔者给出一个应用场景:你需要一个根据地理信息(城市名或者经纬度)获取天气的应用.可选的API很多,不幸的是,网上提到的Google天气API已经停止服务了(不是被墙):雅虎是英文的,且需要

android使用apache httpclient发送post请求

package com.liuc; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.ht

Apache HttpClient访问网络工具类

1 package com.ztravel.utils; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org

Python学习之异常重试解决方法详解

本文和大家分享的是在使用python 进行数据抓取中,异常重试相关解决办法,一起来看看吧,希望对大家学习python有所帮助. 在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理. 原先的流程: defcrawl_page(url): pass deflog_error(url): pass url = "" try: crawl_page(url) except: log_error(url) 改进后的流程: attempts =

论httpclient上传带参数【commons-httpclient和apache httpclient区别】

需要做一个httpclient上传,然后啪啪啪网上找资料 1.首先以前系统中用到的了commons-httpclient上传,找了资料后一顿乱改,然后测试 PostMethod filePost = new PostMethod(url); filePost.setParameter("system", "vinuxpost"); try { Part part[] = UploadRequestHelper.getPart(request); filePost.s

新旧apache HttpClient 获取httpClient方法

在apache httpclient 4.3版本中对很多旧的类进行了deprecated标注,通常比较常用的就是下面两个类了. DefaultHttpClient -> CloseableHttpClientHttpResponse -> CloseableHttpResponse 目前互联网对外提供的接口通常都是HTTPS协议,有时候接口提供方所示用的证书会出现证书不受信任的提示,chrome访问接口(通常也不会用chrome去访问接口,只是举个例子)会出现这样的提示: 为此我们调用这类接口

使用Apache HttpClient 4.x发送Json数据

Apache HttpClient是Apache提供的一个开源组件,使用HttpClient可以很方便地进行Http请求的调用.自4.1版本开始,HttpClient的API发生了较大的改变,很多方法的调用方式已经和3.x版本不同.本文使用的是当前最新的4.5.3版本. 首先在pom文件中引入httpcomponents依赖包: 1 <dependency> 2 <groupId>org.apache.httpcomponents</groupId> 3 <art

Android 6.0 使用 Apache HttpClient

Android 6.0版本已经已经基本将Apahce Http Client 移除出SDK. 那么问题来了,如果我在以前的项目中使用了Apache HttpClient相关类,怎么办呢? 请看官网给出的答案 Apache HTTP Client Removal Android 6.0 release removes support for the Apache HTTP client. If your app is using this client and targets Android 2.

Spring错误异常重试框架guava-retrying

官网:https://github.com/rholder/guava-retrying Maven:https://mvnrepository.com/artifact/com.github.rholder/guava-retrying 下面示例是基于Spring Boot的,但是都可以用于Spring项目.目前最新版是2.0.0. 集成步骤: POM引入: <!-- https://mvnrepository.com/artifact/com.github.rholder/guava-ret