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

Spring-WS如何正确处理SOAP请求Body中包含两个元素的问题

问题原因说明

Spring WS 中 @RequestPayload 注解默认仅会自动映射 SOAP Body 下的第一个顶级子元素,即便声明多个 @RequestPayload 参数也不会自动解析后续同级元素,所以你当前的写法只能拿到第一个 ProcessApplication 对象。

实现方案(可同时获取两个元素)

方案1:自定义复合请求包装类(推荐,适合JAXB绑定场景)

你可以定义一个包含两个目标元素的JAXB包装类,让Spring WS直接将整个Body内容绑定到该类上:

@XmlRootElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapBodyWrapper {
    @XmlElement(name = "ProcessApplication", namespace = B__NAMESPACE_URI)
    private ProcessApplication application;
    @XmlElement(name = "AdditionalInfo", namespace = A__NAMESPACE_URI)
    private AdditionalInfo addInfo;

    // 省略getter、setter
}

修改端点方法的参数声明:

@PayloadRoots({
        @PayloadRoot(localPart = "ProcessApplication", namespace = B__NAMESPACE_URI),
        @PayloadRoot(localPart = "AdditionalInfo", namespace = A__NAMESPACE_URI),
})
@ResponsePayload
public MyResponse processRequest(@RequestPayload SoapBodyWrapper wrapper) {
    ProcessApplication application = wrapper.getApplication();
    AdditionalInfo addInfo = wrapper.getAddInfo();
    // 业务逻辑
    return response;
}

方案2:手动解析SOAP消息(灵活度最高)

直接注入SOAP消息对象,自行解析Body下的所有子元素,同时可以直接获取Envelope、完整请求内容:

import org.springframework.ws.soap.SoapMessage;
import javax.xml.bind.JAXBContext;
import javax.xml.namespace.QName;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;

@PayloadRoots({
        @PayloadRoot(localPart = "ProcessApplication", namespace = B__NAMESPACE_URI),
        @PayloadRoot(localPart = "AdditionalInfo", namespace = A__NAMESPACE_URI),
})
@ResponsePayload
public MyResponse processRequest(SoapMessage soapMessage) throws Exception {
    // 获取Envelope、Body对象
    SoapEnvelope envelope = soapMessage.getEnvelope();
    SoapBody body = envelope.getBody();

    // 分别解析两个子元素
    JAXBContext jaxbContext = JAXBContext.newInstance(ProcessApplication.class, AdditionalInfo.class);
    ProcessApplication application = (ProcessApplication) jaxbContext.createUnmarshaller()
            .unmarshal(body.getChildElements(new QName(B__NAMESPACE_URI, "ProcessApplication")).next());
    AdditionalInfo addInfo = (AdditionalInfo) jaxbContext.createUnmarshaller()
            .unmarshal(body.getChildElements(new QName(A__NAMESPACE_URI, "AdditionalInfo")).next());

    // 获取完整请求原始内容
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    soapMessage.writeTo(baos);
    String fullRequestContent = baos.toString(StandardCharsets.UTF_8);

    // 业务逻辑
    return response;
}

注:JAXBContext可以提前配置为Spring Bean注入,避免重复创建影响性能。

完整请求、Envelope、Body的读取方式

除了上述方案2中直接注入SoapMessage读取的方式外,也可以通过注入MessageContext获取相关对象:

public MyResponse processRequest(MessageContext messageContext) {
    SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();
    // 后续操作和方案2一致
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 11:09:02