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

Spring Integration:HTTP消息转SoapMessage及空请求处理问题

解决方案:同一端点处理SOAP与空POST请求的Spring Integration实现

核心思路

通过Http.inboundGateway统一接收所有POST请求,允许空请求体;利用自定义消息转换器自动将非空XML请求体转换为SoapMessage,再通过路由分别处理SOAP消息和空请求,全程借助Spring Integration及Spring WS的原生能力完成类型转换,无需手动实现String到SoapMessage的转换逻辑。

步骤1:配置依赖

确保项目引入Spring WS核心及SAAJ(SOAP with Attachments API for Java)依赖,用于SOAP消息处理:

<!-- Maven依赖示例 -->
<dependency>
    <groupId>org.springframework.ws</groupId>
    <artifactId>spring-ws-core</artifactId>
    <version>3.1.2</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.messaging.saaj</groupId>
    <artifactId>saaj-impl</artifactId>
    <version>1.5.3</version>
</dependency>

步骤2:自定义Http消息转换器

实现AbstractHttpMessageConverter,自动识别空请求体并返回null,非空请求体则用Spring WS的SoapMessageFactory转换为SoapMessage:

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.SoapMessageFactory;
import javax.xml.soap.SOAPException;
import java.io.IOException;
import java.util.Collections;

public class CustomSoapHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    private final SoapMessageFactory soapMessageFactory;

    public CustomSoapHttpMessageConverter(SoapMessageFactory soapMessageFactory) {
        super(MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_SOAP_XML);
        this.soapMessageFactory = soapMessageFactory;
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return SoapMessage.class.isAssignableFrom(clazz) || Void.class.isAssignableFrom(clazz);
    }

    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        InputStream body = inputMessage.getBody();
        // 判断请求体是否为空
        if (body.available() == 0) {
            return null;
        }
        try {
            // 利用Spring WS工厂将输入流转换为SoapMessage
            return soapMessageFactory.createWebServiceMessage(body);
        } catch (SOAPException e) {
            throw new HttpMessageNotReadableException("无法创建SOAP消息", e, inputMessage);
        }
    }

    @Override
    protected void writeInternal(Object payload, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        // 处理SOAP响应输出
        if (payload instanceof SoapMessage) {
            ((SoapMessage) payload).writeTo(outputMessage.getBody());
        }
    }
}

步骤3:配置Http Inbound Gateway

配置统一接收端点,使用自定义转换器处理请求体转换,并允许空请求体:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway;
import org.springframework.messaging.MessageChannel;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;

@Configuration
public class IntegrationConfig {

    @Bean
    public HttpRequestHandlingMessagingGateway httpInboundGateway(SoapMessageFactory soapMessageFactory) {
        HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway();
        // 设置端点路径及请求方法
        gateway.setRequestMapping(mapping -> mapping.path("/mixed-endpoint").methods(HttpMethod.POST));
        // 配置自定义消息转换器
        gateway.setMessageConverters(Collections.singletonList(new CustomSoapHttpMessageConverter(soapMessageFactory)));
        // 允许空请求体
        gateway.setEmptyPayloadAccepted(true);
        // 输出到请求路由通道
        gateway.setOutputChannel(requestRoutingChannel());
        return gateway;
    }

    @Bean
    public SoapMessageFactory soapMessageFactory() {
        // 使用SAAJ实现的SOAP消息工厂
        return new SaajSoapMessageFactory();
    }

    @Bean
    public MessageChannel requestRoutingChannel() {
        return new org.springframework.integration.channel.DirectChannel();
    }
}

步骤4:配置请求路由

根据请求体是否为null,将请求路由到不同的处理通道:

import org.springframework.context.annotation.Bean;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.router.ExpressionEvaluatingRouter;
import org.springframework.messaging.MessageChannel;

@Configuration
public class RouterConfig {

    @Bean
    public ExpressionEvaluatingRouter requestRouter() {
        // 通过SpEL表达式判断payload是否为空,路由到对应通道
        ExpressionEvaluatingRouter router = new ExpressionEvaluatingRouter("payload == null ? 'emptyRequestChannel' : 'soapProcessingChannel'");
        router.setChannelMapping("emptyRequestChannel", emptyRequestChannel());
        router.setChannelMapping("soapProcessingChannel", soapProcessingChannel());
        return router;
    }

    @Bean
    public IntegrationFlow routingFlow() {
        return IntegrationFlows.from(requestRoutingChannel())
                .route(requestRouter())
                .get();
    }

    @Bean
    public MessageChannel emptyRequestChannel() {
        return new org.springframework.integration.channel.DirectChannel();
    }

    @Bean
    public MessageChannel soapProcessingChannel() {
        return new org.springframework.integration.channel.DirectChannel();
    }
}

步骤5:实现业务处理逻辑

分别实现空请求和SOAP消息的处理流程:

import org.springframework.context.annotation.Bean;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.ws.soap.SoapMessage;

@Configuration
public class HandlerConfig {

    // 处理空请求的流程
    @Bean
    public IntegrationFlow emptyRequestHandlerFlow() {
        return IntegrationFlows.from(emptyRequestChannel())
                .handle((payload, headers) -> {
                    // 自定义空请求处理逻辑,比如返回默认响应
                    return "空请求已处理";
                })
                .get();
    }

    // 处理SOAP消息的流程,直接接收SoapMessage参数
    @Bean
    public IntegrationFlow soapMessageHandlerFlow(SoapMessageService soapMessageService) {
        return IntegrationFlows.from(soapProcessingChannel())
                .handle(soapMessageService)
                .get();
    }

    @Bean
    public SoapMessageService soapMessageService() {
        return new SoapMessageService();
    }
}

// 你的SOAP业务服务类,直接接收SoapMessage参数
public class SoapMessageService {
    public Object handleSoapMessage(SoapMessage soapMessage) {
        // 处理SOAP消息逻辑
        return soapMessage.getSoapBody().getPayloadSource();
    }
}

方案优势

  1. 完全复用Spring原生能力:借助Spring WS的SoapMessageFactory和消息转换器完成类型转换,无需手动解析XML字符串。
  2. 逻辑清晰解耦:通过路由分离空请求与SOAP请求的处理逻辑,便于维护扩展。
  3. 符合协议要求:统一端点接收所有请求,满足同一HTTP端点混合SOAP与空POST的协议需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:07:02