如何仅针对Http状态码500配置RetryTemplate?
Hey there! I see you're trying to configure Spring Retry to only retry REST calls that return a 500 error, but your current setup isn't targeting exactly that scenario. Let's break down the issue and fix it step by step.
The Problem with Your Current Configuration
Your existing code uses SimpleRetryPolicy with HttpServerErrorException.class as the retryable exception. The catch here is that HttpServerErrorException covers all 5xx status codes (like 502 Bad Gateway, 503 Service Unavailable, etc.), not just 500. That's why your retry logic is probably triggering for more errors than you want.
The Solution: Custom Retry Policy for 500 Errors
We need to create a custom retry policy that checks both the exception type and the specific HTTP status code. Here's how to adjust your RetryTemplate bean:
import org.springframework.http.HttpStatus; import org.springframework.http.HttpServerErrorException; import org.springframework.retry.RetryContext; import org.springframework.retry.policy.SimpleRetryPolicy; import org.springframework.retry.support.RetryTemplate; import org.springframework.retry.backoff.FixedBackOffPolicy; @Bean("restRetryTemplate") public RetryTemplate retryTemplate() { // Custom retry policy that targets only 500 Internal Server Errors SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy() { @Override public boolean canRetry(RetryContext context) { Throwable lastException = context.getLastThrowable(); // Check if the exception is an HttpServerErrorException AND status code is 500 if (lastException instanceof HttpServerErrorException) { HttpServerErrorException serverError = (HttpServerErrorException) lastException; return serverError.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR; } // Fallback to default behavior for other exceptions return super.canRetry(context); } }; // Set maximum retry attempts to 3 retryPolicy.setMaxAttempts(3); FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(1500); // 1.5 seconds between retries RetryTemplate retryTemplate = new RetryTemplate(); retryTemplate.setRetryPolicy(retryPolicy); retryTemplate.setBackOffPolicy(backOffPolicy); return retryTemplate; }
Key Changes Explained:
- We override
canRetry()inSimpleRetryPolicyto add an extra check: after confirming it's anHttpServerErrorException, we verify the status code isHttpStatus.INTERNAL_SERVER_ERROR(which maps to 500). - This ensures only 500 errors trigger retries, while other 5xx errors (or non-server errors) won't be retried.
Important Notes
- Ensure RestTemplate Throws the Right Exception: Make sure your
RestTemplateis using the defaultDefaultResponseErrorHandler(or a custom one) that throwsHttpServerErrorExceptionfor 5xx responses. If your error handler swallows these exceptions, the retry logic won't pick them up. - Java Version Compatibility: This code works with Spring 5+ (which aligns with Java 8+). For older Spring versions, you might need to use
serverError.getStatusCode().value() == 500instead of the enum comparison.
Example Usage with Java 8 Lambda
Once your bean is configured correctly, you can use it with Lambda expressions like this:
@Autowired @Qualifier("restRetryTemplate") private RetryTemplate restRetryTemplate; // ... YourResponse response = restRetryTemplate.execute(context -> restTemplate.getForObject("https://your-api-endpoint.com/resource", YourResponse.class) );
That should do the trick! Now your retries will only kick in when the API returns a 500 error.
内容的提问来源于stack exchange,提问作者VaibS

