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

Spring Boot服务读取消费者SOAP请求体为空问题问询

Spring Boot读取SOAP请求体为null的解决方法

你的问题核心在于:消费者发送的SOAP请求是包裹在Envelope(信封)和Body结构中的,直接用@RequestBody绑定Request对象会因为根节点不匹配、命名空间未正确映射导致解析失败,最终请求体为null。以下是具体解决方案:

1. 定义SOAP信封映射实体类

首先需要创建对应SOAP信封结构的实体类,用JAXB注解处理命名空间和节点映射:

SoapEnvelope.java

import jakarta.xml.bind.annotation.*;

@XmlRootElement(name = "Envelope", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class SoapEnvelope {

    @XmlElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
    private SoapBody body;

    // Getter & Setter
    public SoapBody getBody() {
        return body;
    }

    public void setBody(SoapBody body) {
        this.body = body;
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    public static class SoapBody {

        @XmlElement(name = "Request", namespace = "http://www.test.com/bs/testing")
        private Request request;

        // Getter & Setter
        public Request getRequest() {
            return request;
        }

        public void setRequest(Request request) {
            this.request = request;
        }
    }
}

修正原有实体类的命名空间注解

确保你的Request、Message等实体类正确添加命名空间映射:

Request.java

import jakarta.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://www.test.com/bs/testing")
public class Request {

    @XmlElement(name = "message", namespace = "http://www.test.com/bs/testing")
    private Message message;

    // Getter & Setter
    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }
}

Message.java

import jakarta.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://www.test.com/bs/testing")
public class Message {

    @XmlElement(name = "m_control", namespace = "http://www.test.com/bs/testing")
    private MControl mControl;

    @XmlElement(name = "person", namespace = "http://www.test.com/bs/testing")
    private Person person;

    // Getter & Setter
    public MControl getMControl() {
        return mControl;
    }

    public void setMControl(MControl mControl) {
        this.mControl = mControl;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

MControl、Person等子实体类同理,需为每个字段添加对应命名空间的@XmlElement注解。

2. 修改控制器代码解析SOAP信封

将控制器的入参改为SoapEnvelope,从信封中提取真正的Request对象:

@RestController
@RequiredArgsConstructor
@Slf4j
public class SoapController {

    private final SoapService soapService;
    
    @RequestMapping(value = "/validate/getResponse", method = RequestMethod.POST, consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseEntity<Response> readSOAPRequest(@RequestBody SoapEnvelope soapEnvelope) throws Exception {
        Request request = soapEnvelope.getBody().getRequest();
        log.info("Request++: " + request.getMessage().getPerson().getForename());

        Response response = soapService.callService(request);
        return ResponseEntity.ok(response); // 修正返回方式,用ResponseEntity正确包装响应
    }
}

3. 确保JAXB依赖齐全(Spring Boot 3.x需额外添加)

如果使用Spring Boot 3.x,由于Jakarta EE的变更,需要手动引入JAXB相关依赖:

<!-- pom.xml -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <scope>runtime</scope>
</dependency>

核心原因说明

消费者发送的SOAP请求根节点是soapenv:Envelope,而非直接的ver:Request,Spring默认的XML解析无法跳过信封结构直接绑定内部节点,必须先解析完整的SOAP信封,再逐层提取业务请求对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:30