如何在int-http:outbound-gateway中处理设计返回的404状态码?
这个场景我碰到过好多次了——Spring Integration默认会把所有HTTP 4xx、5xx状态码都当成异常处理,但像这种业务上明确预期的404,完全不该走异常流程打断正常聚合。下面给你几个实用的解决思路,你可以根据自己的场景选:
解决Spring Integration中REST 404作为正常业务场景的问题
方案1:让HTTP客户端把404视为正常响应
如果你用RestTemplate或WebClient调用REST服务,可以直接修改客户端配置,让它不对404抛出异常:
针对RestTemplate
自定义一个错误处理器,只把非404的错误状态码判定为异常:
public class CustomRestErrorHandler extends DefaultResponseErrorHandler { @Override public boolean hasError(HttpStatus statusCode) { // 仅将非404的错误状态码视为异常 return statusCode.isError() && statusCode != HttpStatus.NOT_FOUND; } }
然后把这个处理器注入到你的RestTemplate Bean中:
@Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new CustomRestErrorHandler()); return restTemplate; }
针对WebClient(WebFlux场景)
在构建WebClient时,通过onStatus方法指定404不触发异常,而是转为正常响应:
@Bean public WebClient webClient() { return WebClient.builder() .defaultStatusHandler(HttpStatus.NOT_FOUND, clientResponse -> // 可以返回空对象或自定义业务Bean,让流程继续 clientResponse.bodyToMono(YourPayloadBean.class) ) .build(); }
方案2:在Integration流程中捕获并转换404异常
如果不想修改客户端配置,也可以在流程里专门捕获HttpClientErrorException.NotFound(对应404的异常类型),把它转换成正常的业务数据继续流转:
比如在REST调用的负载增强器之后,添加异常处理逻辑:
@Bean public IntegrationFlow mainIntegrationFlow() { return IntegrationFlows.from("inputChannel") // 调用SOAP服务的负载增强器 .enrich(payloadEnricherSpec -> payloadEnricherSpec .requestChannel("soapCallChannel")) // 调用REST服务的负载增强器 .enrich(payloadEnricherSpec -> payloadEnricherSpec .requestChannel("restCallChannel") // 为这个增强器添加异常处理通知 .advice(restErrorHandlingAdvice())) // 后续的结果转换流程 .transform(resultTransformer()) .channel("outputChannel") .get(); } @Bean public Advice restErrorHandlingAdvice() { ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice(); advice.setTrapException(true); // 把捕获到的异常作为payload传入后续处理 advice.setOnFailureExpressionString("#exception"); // 处理404异常,返回标记了未找到状态的业务Bean advice.setOnFailurePayloadExpressionString(""" #exception instanceof T(org.springframework.web.client.HttpClientErrorException.NotFound) ? new com.yourpackage.YourPayloadBean(false) : #exception """); return advice; }
方案3:用专属错误通道处理404
你还可以为REST调用端点指定专门的错误通道,在错误通道里处理404异常后,再把消息送回主流程:
@Bean public IntegrationFlow restCallFlow() { return IntegrationFlows.from("restCallInput") .handle(Rest.outboundGateway("http://your-rest-service/query") .httpMethod(HttpMethod.GET) .expectedResponseType(YourPayloadBean.class)) // 指定404异常会进入这个错误通道 .errorChannel("restErrorChannel") .get(); } @Bean public IntegrationFlow restErrorHandlingFlow() { return IntegrationFlows.from("restErrorChannel") .handle((payload, headers) -> { if (payload instanceof MessagingException msgEx) { Throwable cause = msgEx.getCause(); if (cause instanceof HttpClientErrorException.NotFound) { // 构造正常业务Bean,标记REST未找到数据 YourPayloadBean bean = new YourPayloadBean(); bean.setRestDataFound(false); return bean; } // 非404异常继续抛出或做其他处理 throw msgEx; } return payload; }) // 送回主流程的后续处理通道 .channel("postRestProcessingChannel") .get(); }
以上几种方案都能让404这种正常业务场景不触发Spring Integration的异常流程,顺利完成后续的结果聚合与转换。
内容的提问来源于stack exchange,提问作者Her-Bak
相关产品推荐
相关产品推荐

