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

Spring Boot集成第三方WSDL时SOAP请求缺失操作元素的咨询

问题:Spring Boot集成RPC/Encoded风格WSDL时请求缺失操作元素

我使用WebServiceGatewaySupport和org.jvnet.jaxb2.maven2:maven-jaxb2-plugin:0.15.1集成第三方WSDL,该WSDL在SoapUI中可正常运行,但Spring Boot直接调用时报错:

Method 'ns2:carsRequest' not implemented: method name or namespace not recognized

排查后发现,Java代码生成的请求未用操作元素包裹请求体:SoapUI生成的成功请求包含<pai:GetListCars>元素,但Java生成的payload缺失该部分,示例如下:

正确请求(SoapUI生成):

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:pai="http://my-endpoint.com">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <pai:GetListCars>
            <ns2:carsRequest xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/">
                <lang>EN</lang>
            </ns2:carRequest>
        </pai:GetListCars>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

错误请求(Java生成):

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:pai="http://my-endpoint.com">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns2:carsRequest xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/">
            <lang>EN</lang>
        </ns2:carRequest>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

对应的第三方WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:apachesoap="http://xml.apache.org/xml-soap"
                  xmlns:impl="http://my-endpoint.com"
                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  targetNamespace="http://my-endpoint.com">
    <wsdl:types>
        <schema targetNamespace="http://my-endpoint.com"
                xmlns="http://www.w3.org/2001/XMLSchema">
            <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
            <complexType name="CarsRequest">
                <sequence>
                    <element name="lang" nillable="true" type="soapenc:string"/>
                </sequence>
            </complexType>
            <complexType name="CarsResponse">
                <sequence>
                    <element name="ErrorMessage" nillable="true" type="soapenc:string"/>
                </sequence>
            </complexType>
        </schema>
    </wsdl:types>
    <wsdl:message name="GetListCarsResponse">
        <wsdl:part name="getListCarsReturn" type="impl:CarsResponse"/>
    </wsdl:message>
    <wsdl:message name="GetListCarsRequest">
        <wsdl:part name="carRequest" type="impl:CarsRequest"/>
    </wsdl:message>
    <wsdl:portType name="Garage">
        <wsdl:operation name="GetListCars" parameterOrder="frnreq">
            <wsdl:input message="impl:GetListCarsRequest" name="getListVehiclesRequest"/>
            <wsdl:output message="impl:GetListCarsResponse" name="getListVehiclesResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="GarageSoapBinding"
                  type="impl:Garage">
        <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="GetListCars">
            <wsdlsoap:operation soapAction=""/>
            <wsdl:input name="getListVehiclesRequest">
                <wsdlsoap:body
                        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                        namespace="http://my-endpoint.com" use="encoded"/>
            </wsdl:input>
            <wsdl:output name="getListVehiclesResponse">
                <wsdlsoap:body
                        encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                        namespace="http://my-endpoint.com" use="encoded"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="GarageService">
        <wsdl:port binding="impl:GarageSoapBinding" name="Garage">
            <wsdlsoap:address location="http://localhost:8888"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

不希望修改源WSDL,请问是否有方法添加缺失的元素,或者可以使用其他替代库?


解决方案

一、手动包装请求体(基于现有Spring WS框架)

该WSDL属于RPC/Encoded风格,默认JAXB生成逻辑对这类风格的支持不足,可通过自定义WebServiceMessageCallback手动添加缺失的操作元素:

  1. 实现自定义回调类:
public class RpcSoapCallback implements WebServiceMessageCallback {
    private final String operationName;
    private final String namespaceUri;
    private final String prefix;

    public RpcSoapCallback(String operationName, String namespaceUri, String prefix) {
        this.operationName = operationName;
        this.namespaceUri = namespaceUri;
        this.prefix = prefix;
    }

    @Override
    public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
        SaajSoapMessage soapMessage = (SaajSoapMessage) message;
        SOAPBody soapBody = soapMessage.getSaajMessage().getSOAPBody();
        
        // 移除原请求体元素
        Node originalRequest = soapBody.getFirstChild();
        if (originalRequest == null) return;
        soapBody.removeChild(originalRequest);
        
        // 创建操作元素并包裹原请求体
        SOAPElement operationElement = soapBody.addChildElement(operationName, prefix, namespaceUri);
        operationElement.appendChild(originalRequest);
    }
}
  1. 调用接口时使用该回调:
CarsRequest request = new CarsRequest();
request.setLang("EN");

CarsResponse response = (CarsResponse) getWebServiceTemplate().marshalSendAndReceive(
    "http://localhost:8888",
    request,
    new RpcSoapCallback("GetListCars", "http://my-endpoint.com", "pai")
);

二、更换代码生成插件

maven-jaxb2-plugin对RPC/Encoded风格的支持有限,可替换为对该风格更友好的Apache CXF插件:

在pom.xml中添加配置:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>3.6.2</version>
    <executions>
        <execution>
            <id>generate-soap-client</id>
            <phase>generate-sources</phase>
            <configuration>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>src/main/resources/wsdl/your-service.wsdl</wsdl>
                        <extraargs>
                            <extraarg>-p</extraarg>
                            <extraarg>com.your.package.generated</extraarg>
                            <extraarg>-fe</extraarg>
                            <extraarg>jaxws21</extraarg>
                        </extraargs>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

生成的客户端代码会自动处理RPC/Encoded风格的请求包装逻辑,直接调用即可,无需手动修改请求体。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 07:15:37