我们在进行http请求时,难免会遇到请求失败的情况,失败后需要重新请求,尝试再次获取数据。
Apache的HttpClient提供了异常重试机制,在该机制中,我们可以很灵活的定义在哪些异常情况下进行重试。
今天有个小伙伴,遇到了这样的问题,后来是通过此方法去解决的,
一个爬虫,他请求超过了多少次,自动就超时了,目前还没有找得到具体原因,不过用这个重连机制是完美解决了问题的。好了,代码如下:
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import javax.net.ssl.SSLException;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.ParseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
public class HttpPostUtils {
public String retryPostJson(String uri, String json, int retryCount, int connectTimeout,
int connectionRequestTimeout, int socketTimeout) throws IOException, ParseException {
if (StringUtils.isAnyBlank(uri, json)) {
return null;
}
HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount > retryCount) {
// Do not retry if over max retry count
return false;
}
if (exception instanceof InterruptedIOException) {
// An input or output transfer has been terminated
return false;
}
if (exception instanceof UnknownHostException) {
// Unknown host 修改代码让不识别主机时重试,实际业务当不识别的时候不应该重试,再次为了演示重试过程,执行会显示retryCount次下面的输出
System.out.println("不识别主机重试"); return true;
}
if (exception instanceof ConnectException) {
System.out.println("连接超时,正在重新请求ing...."); return true;
}
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 client = HttpClients.custom().setRetryHandler(httpRequestRetryHandler).build();
HttpPost post = new HttpPost(uri);
// Create request data
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
// Set request body
post.setEntity(entity);
RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build();
post.setConfig(config);
// Response content
String responseContent = null;
CloseableHttpResponse response = null;
try {
response = client.execute(post, HttpClientContext.create());
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
responseContent = EntityUtils.toString(response.getEntity(), Consts.UTF_8.name());
}
} finally {
if (ObjectUtils.anyNotNull(response)) {
response.close();
}
if (ObjectUtils.anyNotNull(client)) {
client.close();
}
}
return responseContent;
}