RequestHandlerRetryAdvice与HttpRequestExecutingMessageHandler重试不生效问题排查
问题分析与解决方案
我来帮你拆解下这个问题——你没触发重试的原因其实是两个关键环节的配置/理解偏差,咱们一步步说:
1. 核心理解误区:不是所有HTTP错误都会触发重试
HttpRequestExecutingMessageHandler这个组件默认的行为是:
- 当遇到连接失败、IO异常、5xx服务器错误这类严重问题时,才会抛出
HttpRequestExecutingMessageHandlerException - 但像404这种客户端错误(2xx以外的非严重状态码),它默认只会把包含状态码的响应封装成消息返回,不会抛出异常
而你配置的RequestHandlerRetryAdvice是基于handler抛出异常这个前提来触发重试的,所以404场景下根本没触发异常,自然不会进入重试流程。
2. 配置缺失:重试策略没指定要处理的异常类型
你的SimpleRetryPolicy只设置了最大重试次数,但默认情况下它只会重试RuntimeException的子类,而且就算后续让404抛出了异常,你也没明确告诉它哪些异常需要重试,这也会导致重试不生效。
解决方案:两步调整配置
第一步:让404这类非2xx状态码抛出异常
在你的httResponseMessageHandler Bean里,添加一行配置,让组件在收到非2xx响应时抛出异常:
handler.setThrowExceptionOnNonSuccess(true);
这样一来,当访问不存在的URL返回404时,组件就会抛出HttpRequestExecutingMessageHandlerException,给重试机制触发的机会。
第二步:配置重试策略,指定要重试的异常类型
修改你的retryPolicy Bean,明确添加需要重试的异常类型:
@Bean public SimpleRetryPolicy retryPolicy(){ SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); // 定义需要重试的异常映射 Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>(); // 针对HTTP请求处理异常重试 retryableExceptions.put(HttpRequestExecutingMessageHandlerException.class, true); // 也可以加上底层IO异常(比如连接超时等) retryableExceptions.put(IOException.class, true); retryPolicy.setRetryableExceptions(retryableExceptions); retryPolicy.setMaxAttempts(5); return retryPolicy; }
进阶:针对特定状态码重试(可选)
如果只想针对404重试,而不是所有非2xx状态,你可以自定义RetryListener,在重试前判断异常里的响应状态码:
public class CustomRetryListener implements RetryListener { @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { Throwable lastThrowable = context.getLastThrowable(); if (lastThrowable instanceof HttpRequestExecutingMessageHandlerException) { ClientHttpResponse response = ((HttpRequestExecutingMessageHandlerException) lastThrowable).getResponse(); return response != null && response.getStatusCode() == HttpStatus.NOT_FOUND; } return true; } // 实现其他空方法... }
然后把这个Listener添加到RetryTemplate中:
retryTemplate.registerListener(new CustomRetryListener());
总结
你的问题本质是:
- 默认情况下404不会触发异常,重试机制没被激活
- 重试策略未明确指定要处理的异常类型
按照上面的两步调整后,访问不存在的URL时应该就能触发你配置的5次重试了。
内容的提问来源于stack exchange,提问作者AbNig
相关产品推荐
相关产品推荐

