如何在HTTP出站调用遇400、413等客户端错误时重发原/修改后消息
在Spring Integration Java DSL HTTP出站调用中处理400/413客户端错误并重发消息
要在Spring Integration Java DSL的HTTP出站调用场景中,针对400(请求错误)、413(负载过大)等客户端错误实现消息重发(原始消息或修改后消息),可以通过自定义重试通知(Advice)结合异常分类重试策略来实现,具体步骤如下:
1. 为HTTP出站端点配置重试通知
修改集成流,为HTTP出站的handle方法绑定自定义重试通知,让指定错误触发重试逻辑:
@Bean private IntegrationFlow myChannel() { IntegrationFlowBuilder builder = IntegrationFlows.from(queue) .handle( // 配置HTTP POST请求示例 Http.outboundGateway("http://your-target-url") .httpMethod(HttpMethod.POST) .expectedResponseType(String.class), e -> e.advice(myRetryAdvice()) // 绑定自定义重试通知 ) .channel(MessageChannels.publishSubscribe(channel2)); return builder.get(); }
2. 自定义异常分类重试策略,指定触发重试的客户端错误
创建专属重试策略,仅对400、413等目标客户端错误触发重试,其他错误直接跳过:
class ClientErrorClassifierRetryPolicy extends ExceptionClassifierRetryPolicy { public ClientErrorClassifierRetryPolicy() { // 配置最大重试次数:最多重试2次 final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(); simpleRetryPolicy.setMaxAttempts(2); // 异常分类逻辑:精准匹配目标错误码 this.setExceptionClassifier(classifiable -> { if (classifiable instanceof HttpClientErrorException) { HttpStatus statusCode = ((HttpClientErrorException) classifiable).getStatusCode(); // 仅对400、413错误触发重试 if (statusCode == HttpStatus.BAD_REQUEST || statusCode == HttpStatus.PAYLOAD_TOO_LARGE) { return simpleRetryPolicy; } // 其他客户端错误不重试 return new NeverRetryPolicy(); } // 非客户端错误直接终止 return new NeverRetryPolicy(); }); } }
3. 实现重试通知,支持修改消息后重发
重写RequestHandlerRetryAdvice的open方法,在重试前获取原始消息并修改,替换到重试上下文,让重试时使用新消息:
@Bean public Advice myRetryAdvice() { RequestHandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice() { @Override public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> callback) { // 从重试上下文取出失败的原始消息 Message<String> originalMsg = (Message<String>) retryContext.getAttribute(ErrorMessageUtils.FAILED_MESSAGE_CONTEXT); // 根据业务需求修改消息,比如压缩负载、修正请求参数 Message<String> updatedMsg = MessageBuilder.fromMessage(originalMsg) .setPayload("修改后的请求内容") // 示例:替换消息体 .build(); // 将修改后的消息放回上下文,重试时会使用该消息 retryContext.setAttribute(ErrorMessageUtils.FAILED_MESSAGE_CONTEXT, updatedMsg); return super.open(retryContext, callback); } }; // 为重试通知绑定自定义的客户端错误重试策略 retryAdvice.setRetryPolicy(new ClientErrorClassifierRetryPolicy()); return retryAdvice; }
4. 可选:错误通道处理重试失败的消息
如果所有重试都失败,可通过专属错误通道处理最终失败的消息:
@Bean private IntegrationFlow defaultErrorChannel() { return IntegrationFlows.from("errorChannel") .handle(message -> { // 执行重试失败后的逻辑:记录日志、发送告警等 ErrorMessage errorMessage = (ErrorMessage) message; System.err.println("重试全部失败,错误详情:" + errorMessage.getPayload().getMessage()); }) .get(); }
内容的提问来源于stack exchange,提问作者sophopile
相关产品推荐
相关产品推荐

