Java 强制重试特定的 http 状态代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22827291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force retry on specific http status code
提问by Cacovsky
Dealing with a specific website, sometimes I receive a http response with status code 403. I wanted to re-execute the request in such cases (because, in my specific situation, this server throws a 403 when it is actually overloaded). I tried to use a ResponseHandler
together with a StandardHttpRequestRetryHandler
, but it didn't work the way I hoped; I expected that throwing an exception in the ResponseHandler
would trigger the StandardHttpRequestRetryHandler
, but it does not seems to be the case. How can I achieve the desired functionality?
处理特定网站时,有时我会收到状态码为 403 的 http 响应。我想在这种情况下重新执行请求(因为,在我的特定情况下,该服务器在实际过载时会抛出 403)。我尝试将 aResponseHandler
与a一起使用StandardHttpRequestRetryHandler
,但没有按照我希望的方式工作;我预计在 中抛出异常ResponseHandler
会触发StandardHttpRequestRetryHandler
,但似乎并非如此。我怎样才能实现所需的功能?
Here is a sample code that illustrates my situation:
这是一个示例代码,说明了我的情况:
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);
}
}
采纳答案by ok2c
Try using a custom ServiceUnavailableRetryStrategy
尝试使用自定义 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();
回答by morgano
You can do it by manually checking the status code, something like this:
您可以通过手动检查状态代码来完成,如下所示:
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);
You would need to add some things like retrying a predefined number of times before throwing a final exception and catching some checked exceptions (like the InterruptedException thrown by Thread.sleep()
), but basically the code shows the main idea.
您需要添加一些内容,例如在抛出最终异常之前重试预定义的次数并捕获一些已检查的异常(如 抛出的 InterruptedException Thread.sleep()
),但基本上代码显示了主要思想。