1、 HttpClient异常重试
当请求发生异常时,通过异常处理机制自动重新请求。
2、前提:
被请求的方法必须是幂等的:就是多次请求服务端结果应该是准确且一致的。
适合的方法:比如根据ID,修改人员姓名,无论请求多次结果都是一样,这就是幂等。
不适合的方法:比如减少账号50元,多次请求将多次扣减,
3、实现方式:
想要实现异常重试,需要实现它提供的一个接口
HttpRequestRetryHandler,并实现retryRequest方法。
然后set到HttpClient中。该httpClient就具备了重试机制
4、HttpClient提供了标准和默认两个实现类
4.1 StandardHttpRequestRetryHandler
该类默认几个方法为幂等,如PUT,GET,HEAD等POST外的方法,如果自定义可以参考他的实现方式,
4.2 DefaultHttpRequestRetryHandler
略
5、demo
本文为了演示重试机制,自定义了一个本文通过自定义一个实现类,为了让大家看到重试的效果,将不识别的主机异常,让它重试,代码如下,
在实现的
retryRequest方法中,遇到不识别主机异常,返回true,请求将重试。最多重试请求5次
package httpcomponents;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.*;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
/**
* Created by shuangjun.yang on 2016/4/1.
*/
public class HttpRetryCustomTest {
public static void main(String[] args){
HttpRequestRetryHandler httpRequestRetryHandle = new StandardHttpRequestRetryHandler(1,false);
HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= 5) {
// Do not retry if over max retry count
return false;
}
if (exception instanceof InterruptedIOException) {
// Timeout
return false;
}
if (exception instanceof UnknownHostException) {
// Unknown host 修改代码让不识别主机时重试,实际业务当不识别的时候不应该重试,再次为了演示重试过程,执行会显示5次下面的输出
System.out.println("不识别主机重试");
return true;
}
if (exception instanceof ConnectTimeoutException) {
// Connection refused
return false;
}
if (exception instanceof SSLException) {
// SSL handshake exception
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// Retry if the request is considered idempotent
return true;
}
return false;
}
};
CloseableHttpClient httpClient = HttpClients.custom()
.setRetryHandler(httpRequestRetryHandler)
.build();
HttpGet httpGet = new HttpGet("http://www.begincodee.net"); //不存在的域名
try {
HttpResponse response = httpClient.execute(httpGet, HttpClientContext.create());
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity));
} catch (IOException e) {
e.printStackTrace();
}
}
}