如何在超类异常上实现retry而不是runtimeexception,但是我的代码抛出restclientexception?

gmol1639  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(333)

这是我的重试代码:

@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扩展到各种其他异常。
如何实现对非超类异常的重试逻辑?

7bsow1i6

7bsow1i61#

你的代码不会抛出 RestClientException ,它抛出 ServerErrorException (你接住它,扔一个新的)。
所以当你使用 RuntimeException 它确实有效,就像 ServerErrorException 适合。要么更改catch子句以抛出原始异常,要么使用 ServerErrorException 在注解上。

ffx8fchx

ffx8fchx2#

实际上,您可以在“value”属性中设置任何异常,而不仅仅是基异常。此外,还可以指定多个异常:

@Retryable(value = {FirstException.class, SecondException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))

相关问题