处理特定网站时,有时我会收到状态码为403的http响应。我想在这种情况下重新执行请求(因为,在我的特定情况下,此服务器在实际超载时会抛出403) 。我试图将ResponseHandler
与StandardHttpRequestRetryHandler
一起使用,但它并没有像我希望的那样工作;我期望在ResponseHandler
中抛出异常会触发StandardHttpRequestRetryHandler
,但似乎并非如此。如何实现所需的功能?
以下示例代码说明了我的情况:
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
public class Main {
public static void main(String[] args) throws Exception {
// a response handler that throws an exception if status is not 200
ResponseHandler<String> responseHandler = new ResponseHandler<String> () {
@Override
public String handleResponse(HttpResponse response) throws
ClientProtocolException, IOException
{
System.out.println("-> Handling response");
if (response.getStatusLine().getStatusCode() != 200){
// I expected this to trigger the retryHandler
throw new ClientProtocolException("Status code not supported");
}
return EntityUtils.toString(response.getEntity());
}
};
StandardHttpRequestRetryHandler retryHandler =
new StandardHttpRequestRetryHandler(5, true)
{
@Override
public boolean retryRequest(
final IOException exception,
final int executionCount,
final HttpContext context)
{
System.out.println("-> Retrying request");
return super.retryRequest(exception, executionCount, context);
}
};
// my client with my retry handler
HttpClient client = HttpClients
.custom()
.setRetryHandler(retryHandler)
.build();
// my request
HttpUriRequest request = RequestBuilder
.create("GET")
.setUri("http://httpstat.us/403") //always returns 403
.build();
String contents = client.execute(request, responseHandler);
System.out.println(contents);
}
}
答案 0 :(得分:21)
尝试使用自定义ServiceUnavailableRetryStrategy
CloseableHttpClient client = HttpClients.custom()
.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
@Override
public boolean retryRequest(
final HttpResponse response, final int executionCount, final HttpContext context) {
int statusCode = response.getStatusLine().getStatusCode();
return statusCode == 403 && executionCount < 5;
}
@Override
public long getRetryInterval() {
return 0;
}
})
.build();
答案 1 :(得分:1)
您可以通过手动检查状态代码来执行此操作,如下所示:
CloseableHttpResponse response = null;
boolean success = false;
while(!success) {
response = client.execute(httpGet);
int status = response.getStatusLine().getStatusCode();
success = (status == 200);
if (!success) {
if(status == 403) {
Thread.sleep(2000); // wait 2 seconds before retrying
} else {
throw new RuntimeException("Something went wrong: HTTP status: " + status);
}
}
}
String contents = EntityUtils.toString(response.getEntity());
response.close();
// ....
System.out.println(contents);
您需要添加一些内容,例如在抛出最终异常并捕获一些已检查的异常(例如Thread.sleep()
抛出的InterruptedException)之前重试预定义次数,但基本上代码显示主要想法。 / p>