这是我的重试代码:
@Retryable(value = RestClientException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000))
public <T, S> ResponseEntity<T> sendPostRequest(String url,
S requestObject,
Class<T> responseClazz,
HttpHeaders headers) {
ResponseEntity<T> response = null;
try {
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<S> request = new HttpEntity<>(requestObject, headers);
response = restTemplate.exchange(url, HttpMethod.POST, request, responseClazz);
return response;
} catch(HttpStatusCodeException ex) {
response = new ResponseEntity(ex.getResponseBodyAsString(), ex.getStatusCode());
} catch(RestClientException rce) {
log.error("Error occurred.: {}", rce.getMessage());
throw new ServerErrorException("Exception throw");
}
return response;
}
登录控制台:
Error occurred.: I/O error on POST request for "https://thirdpartyapi.com": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
根据我的代码,它需要重试3次,然后它会抛出错误。但这是第一次尝试。
当我将可重试注解更改为:
@Retryable(value = RuntimeException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000))
现在我的代码以正确的逻辑工作。
runtimeexception是restclientexception的超类,SpringRetry只对超类异常起作用。
但是我想对我的代码有更多的控制,并为更少的异常实现重试逻辑。runtimeexception扩展到各种其他异常。
如何实现对非超类异常的重试逻辑?
2条答案
按热度按时间7bsow1i61#
你的代码不会抛出
RestClientException
,它抛出ServerErrorException
(你接住它,扔一个新的)。所以当你使用
RuntimeException
它确实有效,就像ServerErrorException
适合。要么更改catch子句以抛出原始异常,要么使用ServerErrorException
在注解上。ffx8fchx2#
实际上,您可以在“value”属性中设置任何异常,而不仅仅是基异常。此外,还可以指定多个异常: