Spring Integration DSL配置Http.outboundGateway的错误处理与重试
Spring Integration DSL: REST接口重试与状态码特定处理
嘿,我刚好配置过类似的需求,给你梳理下怎么用Spring Integration DSL实现REST调用失败重试3次,同时根据返回状态码执行不同操作的方案,直接上代码和实用解释:
第一步:配置重试机制
我们用RequestHandlerRetryAdvice来实现重试逻辑,可以指定重试次数、重试的异常类型,甚至添加重试间隔的退避策略:
@Bean public RequestHandlerRetryAdvice restRetryAdvice() { RequestHandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice(); retryAdvice.setRetryTemplate(restRetryTemplate()); // 重试3次都失败的话,把错误消息发到错误通道,后续可以统一处理 retryAdvice.setRecoveryCallback(new ErrorMessageSendingRecoverer(errorChannel())); return retryAdvice; } @Bean public RetryTemplate restRetryTemplate() { RetryTemplate retryTemplate = new RetryTemplate(); // 1. 设置重试规则:最多3次,只对服务器错误(5xx)重试 SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); retryPolicy.setMaxAttempts(3); Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>(); // 只对5xx的服务器异常重试,4xx客户端错误不重试(你可以根据需求调整) retryableExceptions.put(HttpServerErrorException.class, true); retryableExceptions.put(HttpClientErrorException.class, false); retryPolicy.setRetryableExceptions(retryableExceptions); // 2. 设置重试间隔:每次重试间隔1秒(可选,避免频繁请求压垮服务) FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); backOffPolicy.setBackOffPeriod(1000); retryTemplate.setRetryPolicy(retryPolicy); retryTemplate.setBackOffPolicy(backOffPolicy); return retryTemplate; } @Bean public MessageChannel errorChannel() { return new DirectChannel(); }
第二步:配置状态码差异化处理
接下来用ExpressionEvaluatingRequestHandlerAdvice捕获不同的HTTP状态码,把状态码放到消息头里,方便后续路由到不同的处理逻辑:
@Bean public ExpressionEvaluatingRequestHandlerAdvice statusCodeHandlingAdvice() { ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(); // 捕获非2xx状态码的异常,提取状态码放到header,同时构建自定义消息体 advice.setOnSuccessExpressionString( "payload instanceof org.springframework.web.client.HttpStatusCodeException ? " + "T(org.springframework.integration.support.MessageBuilder).withPayload('请求返回非2xx状态码: ' + payload.statusCode) " + ".setHeader('http_status_code', payload.statusCode).build() : payload" ); // 让Advice返回处理后的结果,而不是抛出异常 advice.setReturnFailureExpressionResult(true); return advice; }
第三步:整合到你的IntegrationFlow里
把上面两个Advice应用到HTTP Outbound Gateway,然后根据状态码header路由到不同的处理分支:
@Bean public IntegrationFlow performCreate() { return IntegrationFlows.from("createFlow") // 配置HTTP请求 .handle(Http.outboundGateway("http://localhost:8080/create") .httpMethod(HttpMethod.GET) .expectedResponseType(String.class) .requestFactory(requestFactory()), // 你的requestFactory实现 // 同时应用重试和状态码处理的Advice e -> e.advice(restRetryAdvice(), statusCodeHandlingAdvice())) // 根据状态码路由到不同处理逻辑 .route(header("http_status_code"), status -> { HttpStatus httpStatus = (HttpStatus) status; if (httpStatus.is4xxClientError()) { return "clientErrorProcessingChannel"; } else if (httpStatus.is5xxServerError()) { return "serverErrorProcessingChannel"; } else { return "successProcessingChannel"; } }) .get(); } // 客户端错误(4xx)处理流程 @Bean public IntegrationFlow clientErrorFlow() { return IntegrationFlows.from("clientErrorProcessingChannel") .handle(message -> { // 这里写你的4xx处理逻辑:比如日志记录、返回友好提示等 System.out.println("处理客户端错误: " + message.getPayload()); }) .get(); } // 服务器错误(5xx)处理流程 @Bean public IntegrationFlow serverErrorFlow() { return IntegrationFlows.from("serverErrorProcessingChannel") .handle(message -> { // 这里写你的5xx处理逻辑:比如告警通知、降级处理等 System.out.println("处理服务器错误: " + message.getPayload()); }) .get(); } // 成功请求处理流程 @Bean public IntegrationFlow successFlow() { return IntegrationFlows.from("successProcessingChannel") .handle(message -> { // 正常处理返回结果 System.out.println("请求成功,返回内容: " + message.getPayload()); }) .get(); }
额外说明
- 如果需要更精细的重试控制(比如指数退避、不同异常不同重试次数),可以替换
FixedBackOffPolicy为ExponentialBackOffPolicy,或者自定义RetryPolicy。 - 如果你不想用Advice,也可以通过
errorChannel来统一处理错误,然后在错误通道里解析状态码再路由,但用Advice的方式更直接,和HTTP请求绑定更紧密。
内容的提问来源于stack exchange,提问作者nagendra
相关产品推荐
相关产品推荐

