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

Spring-WS如何在无Request后缀时生成含输入的SOAP服务

问题

需要基于供应商提供的行业标准XSD生成SOAP Web服务(消费者仅支持SOAP),XSD中输入输出元素定义如下:

<xsd:element name="getData">
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="Request" type="CT_getDataRequest" minOccurs="1" maxOccurs="1"/>
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>
<xsd:element name="getDataResponse">
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="Response" type="CT_getDataResponse" minOccurs="1" maxOccurs="1"/>
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>

Spring-WS端点和配置代码如下:

端点代码

@Endpoint
@RequiredArgsConstructor
public class DataEndpoint {
    private static final String NAMESPACE_URI = "http://www.machine-config.net/namespace/data";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getData")
    @ResponsePayload
    public GetDataResponse getData(@RequestPayload GetData request) {
        // 业务逻辑实现
    }
}

WSDL配置代码

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
        messageDispatcherServlet.setApplicationContext(applicationContext);
        messageDispatcherServlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(messageDispatcherServlet, "/ws/*");
    }

    @Bean(name = "dataDefinition")
    public DefaultWsdl11Definition dataWsdl11Definition() {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("dataServicePortType");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://www.machine-config.net/namespace");
        wsdl11Definition.setSchemaCollection(dataSchemas());
        
        return wsdl11Definition;
    }

    @Bean(name = "dataSchema")
    public XsdSchemaCollection dataSchemas() {
        CommonsXsdSchemaCollection xsds = new CommonsXsdSchemaCollection(new ClassPathResource("xsd/data-2.18.1433.2.xsd"));
        xsds.setUriResolver(new DefaultURIResolver());
        xsds.setInline(true);
        return xsds;
    }
}

生成的WSDL中getData操作仅包含输出部分,缺失输入:

<wsdl:operation name="getData">
    <wsdl:output message="sch0:getDataResponse" name="getDataResponse"> </wsdl:output>
</wsdl:operation>

已知修改XSD将getData改为getDataRequest可正常生成输入,但无法修改供应商提供的XSD,需解决Spring-WS识别无Request后缀输入参数的问题。


解决方案

Spring-WS的DefaultWsdl11Definition默认通过*Request/*Response后缀匹配生成WSDL操作,因此需要自定义操作映射逻辑,以下两种方法均可解决:

方法1:手动添加WSDL操作

直接在DefaultWsdl11Definition配置中手动指定getData操作的输入输出消息,精准匹配XSD中的元素:

修改dataWsdl11Definition方法:

@Bean(name = "dataDefinition")
public DefaultWsdl11Definition dataWsdl11Definition(XsdSchemaCollection dataSchemas) {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("dataServicePortType");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setTargetNamespace("http://www.machine-config.net/namespace");
    wsdl11Definition.setSchemaCollection(dataSchemas);

    // 手动构建getData操作,指定输入输出的QName
    String inputNamespace = "http://www.machine-config.net/namespace/data";
    QName inputQName = new QName(inputNamespace, "getData");
    QName outputQName = new QName(inputNamespace, "getDataResponse");

    WsdlOperationDefinition getDataOperation = new WsdlOperationDefinition("getData");
    getDataOperation.setInput(new WsdlInputDefinition(inputQName));
    getDataOperation.setOutput(new WsdlOutputDefinition(outputQName));

    wsdl11Definition.getOperations().add(getDataOperation);

    return wsdl11Definition;
}

方法2:自定义操作构建器

如果存在多个类似的无Request后缀的操作,可自定义OperationBuilder实现通用匹配逻辑(自动匹配XXX和XXXResponse元素对):

  1. 创建自定义操作构建器类:
import org.springframework.ws.wsdl.wsdl11.DefaultOperationBuilder;
import org.springframework.ws.wsdl.wsdl11.WsdlOperationDefinition;
import org.springframework.ws.wsdl.wsdl11.WsdlInputDefinition;
import org.springframework.ws.wsdl.wsdl11.WsdlOutputDefinition;
import org.springframework.ws.xml.xsd.XsdSchema;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CustomOperationBuilder extends DefaultOperationBuilder {
    @Override
    protected List<WsdlOperationDefinition> buildOperations(XsdSchema schema) {
        List<WsdlOperationDefinition> operations = new ArrayList<>();
        Map<QName, ?> elements = schema.getElementDefinitions();

        for (Map.Entry<QName, ?> entry : elements.entrySet()) {
            QName elementQName = entry.getKey();
            String elementName = elementQName.getLocalPart();
            // 跳过Response后缀的元素,只处理请求元素
            if (!elementName.endsWith("Response")) {
                // 查找对应的Response元素
                QName responseQName = new QName(elementQName.getNamespaceURI(), elementName + "Response");
                if (elements.containsKey(responseQName)) {
                    // 构建操作并添加到列表
                    WsdlOperationDefinition operation = new WsdlOperationDefinition(elementName);
                    operation.setInput(new WsdlInputDefinition(elementQName));
                    operation.setOutput(new WsdlOutputDefinition(responseQName));
                    operations.add(operation);
                }
            }
        }
        return operations;
    }
}
  1. 在WSDL配置中使用自定义构建器:
@Bean(name = "dataDefinition")
public DefaultWsdl11Definition dataWsdl11Definition() {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("dataServicePortType");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setTargetNamespace("http://www.machine-config.net/namespace");
    wsdl11Definition.setSchemaCollection(dataSchemas());
    
    // 设置自定义操作构建器
    wsdl11Definition.setOperationBuilder(new CustomOperationBuilder());

    return wsdl11Definition;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:30:24