You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Integration:如何通过XML/注解配置保留HTTP错误码与响应体?

没问题!我来详细说明如何用Spring XML配置和注解两种方式,实现从出站网关到入站网关的响应中保留HTTP错误码及响应体。

首先明确核心逻辑:默认情况下,Spring Integration的HTTP出站网关收到非2xx响应时会抛出HttpStatusCodeException,导致原始错误响应体和状态码丢失。我们需要通过异常处理机制,把这些错误信息提取出来,封装成正常消息传递回入站网关。

基于Spring XML配置的实现

1. 定义异常处理Advice

这个Advice会捕获出站网关抛出的HTTP异常,将异常导向专门的错误处理通道:

<bean id="httpErrorHandlingAdvice" class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
    <!-- 指定异常发生时的处理逻辑,这里将状态码作为临时结果 -->
    <property name="onFailureExpression" value="T(org.springframework.http.HttpStatus).valueOf(#exception.statusCode.value())"/>
    <!-- 异常将被发送到这个通道进行后续处理 -->
    <property name="failureChannel" ref="errorHandlingChannel"/>
    <!-- 允许将异常处理后的结果作为正常消息返回 -->
    <property name="returnFailureExpressionResult" value="true"/>
</bean>

2. 配置错误处理通道与处理器

创建专门的通道接收异常消息,然后自定义处理器提取错误响应体和状态码:

<!-- 错误处理通道 -->
<int:channel id="errorHandlingChannel"/>

<!-- 自定义错误处理器,提取错误信息并封装成响应 -->
<int:service-activator input-channel="errorHandlingChannel" output-channel="replyChannel">
    <bean class="com.example.HttpErrorResponseHandler"/>
</int:service-activator>

对应的自定义处理器类实现:

public class HttpErrorResponseHandler {
    public Message<?> handleHttpError(Message<Exception> errorMessage) {
        Exception exception = errorMessage.getPayload();
        if (exception instanceof HttpStatusCodeException) {
            HttpStatusCodeException httpEx = (HttpStatusCodeException) exception;
            // 提取原始响应体和状态码
            String responseBody = httpEx.getResponseBodyAsString();
            HttpStatus statusCode = httpEx.getStatusCode();
            
            // 封装成自定义错误响应对象(你可以根据业务需求定义这个类)
            ErrorResponse errorResponse = new ErrorResponse(statusCode.value(), responseBody);
            
            // 构建包含错误信息的消息,同时把状态码放到Header中
            return MessageBuilder.withPayload(errorResponse)
                    .setHeader(HttpHeaders.STATUS_CODE, statusCode)
                    .build();
        }
        // 处理非HTTP异常的情况
        return MessageBuilder.withPayload(exception).build();
    }
    
    // 自定义错误响应对象示例
    public static class ErrorResponse {
        private int statusCode;
        private String responseBody;
        
        // 构造方法、getter/setter省略
        public ErrorResponse(int statusCode, String responseBody) {
            this.statusCode = statusCode;
            this.responseBody = responseBody;
        }
    }
}

3. 配置出站网关并关联Advice

在出站网关中引用刚才定义的异常处理Advice:

<int-http:outbound-gateway id="externalServiceOutboundGateway"
                           request-channel="requestChannel"
                           url="http://your-external-service/api/**"
                           http-method="POST"
                           reply-channel="replyChannel"
                           request-handler-advice-chain="httpErrorHandlingAdvice"/>

<!-- 入站网关关联的请求通道 -->
<int:channel id="requestChannel"/>
<!-- 最终返回给入站网关的响应通道 -->
<int:channel id="replyChannel"/>
基于Spring注解的实现

1. 配置异常处理Advice与通道

用@Bean定义Advice和错误处理通道:

@Configuration
@EnableIntegration
public class GatewayConfig {

    // 异常处理Advice
    @Bean
    public ExpressionEvaluatingRequestHandlerAdvice httpErrorHandlingAdvice() {
        ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
        advice.setOnFailureExpressionString("T(org.springframework.http.HttpStatus).valueOf(#exception.statusCode.value())");
        advice.setFailureChannel(errorHandlingChannel());
        advice.setReturnFailureExpressionResult(true);
        return advice;
    }

    // 错误处理通道
    @Bean
    public MessageChannel errorHandlingChannel() {
        return new DirectChannel();
    }

    // 自定义错误处理器
    @ServiceActivator(inputChannel = "errorHandlingChannel", outputChannel = "replyChannel")
    public Message<?> handleHttpError(Message<Exception> errorMessage) {
        Exception exception = errorMessage.getPayload();
        if (exception instanceof HttpStatusCodeException) {
            HttpStatusCodeException httpEx = (HttpStatusCodeException) exception;
            ErrorResponse errorResponse = new ErrorResponse(httpEx.getStatusCode().value(), httpEx.getResponseBodyAsString());
            return MessageBuilder.withPayload(errorResponse)
                    .setHeader(HttpHeaders.STATUS_CODE, httpEx.getStatusCode())
                    .build();
        }
        return MessageBuilder.withPayload(exception).build();
    }

    // 自定义错误响应对象
    public static class ErrorResponse {
        private int statusCode;
        private String responseBody;

        public ErrorResponse(int statusCode, String responseBody) {
            this.statusCode = statusCode;
            this.responseBody = responseBody;
        }

        // getter/setter省略
    }
}

2. 配置HTTP出站网关

用@Bean创建出站网关实例,并关联异常处理Advice:

@Configuration
public class OutboundGatewayConfig {

    @Bean
    @ServiceActivator(inputChannel = "requestChannel")
    public HttpRequestExecutingMessageHandler externalServiceOutboundGateway() {
        HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("http://your-external-service/api/**");
        handler.setHttpMethod(HttpMethod.POST);
        handler.setOutputChannel(replyChannel());
        // 关联异常处理Advice
        handler.setAdviceChain(Collections.singletonList(httpErrorHandlingAdvice()));
        return handler;
    }

    @Bean
    public MessageChannel requestChannel() {
        return new DirectChannel();
    }

    @Bean
    public MessageChannel replyChannel() {
        return new DirectChannel();
    }

    // 注入之前定义的异常处理Advice
    @Autowired
    private ExpressionEvaluatingRequestHandlerAdvice httpErrorHandlingAdvice;
}

3. 配置入站网关(示例)

最后,你的入站网关只需要关联requestChannel和replyChannel,就能收到包含错误码和响应体的消息了:

@MessagingGateway(defaultRequestChannel = "requestChannel", defaultReplyChannel = "replyChannel")
public interface ApiGateway {
    ErrorResponse callExternalService(YourRequest request);
}

这样配置后,当外部服务返回4xx/5xx错误时,出站网关不会抛出异常,而是将错误码和响应体封装成ErrorResponse对象,通过replyChannel传递回入站网关,完美保留了原始错误信息。

内容的提问来源于stack exchange,提问作者van

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:43:25