当前位置:  开发笔记 > 编程语言 > 正文

当request-element没有以'Request'结尾时,spring-ws生成的wsdl无效

如何解决《当request-element没有以'Request'结尾时,spring-ws生成的wsdl无效》经验,为你挑选了1个好方法。

我必须准备一个web服务来接受已定义的wsdl结构.我按照这里的教程,在这里可以下载测试项目的源代码.

对于像这样的xsd:


    
        
            
        
    

应用程序返回的请求的Wsdl操作正常,如下所示:


    
    
        
        
            
        
        
            
        
    

但是当我将xsd更改为(元素名称中没有'Request')时:


    
        
            
        
    

wsdl无效,并且没有指定:


    
    
        
        
            
        
    

我该如何解决这个问题?如何Request在wsdl中将无元素作为soap操作输入正确显示?



1> A_Di-Matteo..:

根据官方的Spring WS文档,Request/Response后缀是用于自动确定请求/响应的默认值,因此生成预期的WSDL.

DefaultWsdl11Definition,它从XSD架构构建WSDL.此定义迭代在架构中找到的所有元素元素,并为所有元素创建消息.接下来,它为以定义的请求或响应后缀结尾的所有消息创建WSDL操作.默认请求后缀为Request; 默认响应后缀是Response,尽管可以通过分别设置requestSuffix和responseSuffix属性来更改这些后缀.

因此,您可以在提到的示例代码中更改WebServiceConfig配置类中的后缀defaultWsdl11Definition方法,添加以下方法调用:

wsdl11Definition.setRequestSuffix("your-new-prefix-here");

你可以,例如,将其设置为Req代替Request,构建将自动生成一个新的GetCountryReq类,代码ApplicationTestsCountryEndpoint随后将需要手动调整,消除编译错误(因为他们仍然将指向先前存在的GetCountryRequest类),而且还确保更改类中注释的localPart = "getCountryReq"属性.@PayloadRootCountryEndPoint

我试了一下,构建顺利,WSDL也相应更新了.

这是关于将默认后缀更改为另一个后缀.但是如何将其更改为空后缀呢?

wsdl11Definition.setRequestSuffix("");

例外:后缀不能为空.Spring不支持它.根据这个帖子:

基本上,问题是:
我们必须区分哪些架构元素是wsdl消息,哪些不是.
在所有wsdl消息中,我们必须弄清楚哪些是输入(请求)消息.
在所有wsdl消息中,我们必须弄清楚哪些是输出(响应)消息.

DefaultWsdl11Definition用后缀来计算它.或者,更具体地说,它委托给SuffixBasedMessagesProvider和SuffixBasedPortTypesProvider这样做.
因此,如果您有其他一些确定输入/输出消息的首选方法,则必须编写自己的messagesprovider和/或porttypesprovider.

简单地说:Spring-WS没有通用的方法来确定构成请求和响应的内容,而不是使用后缀.

注意:此消息的海报是Arjen Poutsma,DefaultWsdl11Definition该类的作者(根据javadocs),该组件根据这些后缀约定处理自动映射.

但他留下一个敞开的门:写你自己的SuffixBasedMessagesProviderSuffixBasedPortTypesProvider.但是,他还将所有内容保留为私有DefaultWsdl11Definition(这些提供程序被实例化),因此您还需要编写(复制)自己的WSDL11定义映射器.

以下是我遵循的流程:

创建自己的CustomSuffixBasedMessagesProvider,覆盖setRequestSuffix方法并删除对空后缀的检查,在isMessageElement处理新映射所需的方法中

创建自己的CustomSuffixBasedPortTypesProvider,重写setRequestSuffix方法和取消对空后缀的检查,在getOperationNameisInputMessage方法,您将需要处理的新的映射

创建您自己的CustomWsdl11Definition作为现有DefaultWsdl11Definition的副本,并实例化上面创建的您自己的提供程序

更改WebServiceConfig类,defaultWsdl11Definition方法,以使用您自己的CustomWsdl11Definition来应用整个自定义.

但是,空后缀带来了一些挑战,因为它适用于任何元素(也就是说,每个元素都有一个空后缀).这就是为什么我提到的isMessageElement,isInputMessagegetOperationName处理:对生长的WSDL,您可以轻松地结束了对harcoding映射(用于GetCountry要求,GetCountryResponse是响应),或者通过一个属性/图(如建议线程上面提到的),但同样在WebServiceConfig配置类中重复大部分XSD ,使其难以维护,故障排除,共享.

所以,我真的建议不要采取这个旅程并坚持默认后缀(如果可能)或创建一个新的后缀,但避免空后缀(毕竟,它们不被库所允许).

但是自从我开始旅程以来,这是一个有效的解决方案:

MySuffixBasedMessagesProvider自定义类(为简便起见去除进口):

package hello;

public class MySuffixBasedMessagesProvider extends SuffixBasedMessagesProvider {

    protected String requestSuffix = DEFAULT_REQUEST_SUFFIX;

    public String getRequestSuffix() {
        return this.requestSuffix;
    }

    public void setRequestSuffix(String requestSuffix) {
        this.requestSuffix = requestSuffix;
    }

    @Override
    protected boolean isMessageElement(Element element) {
        if (isMessageElement0(element)) {
            String elementName = getElementName(element);
            Assert.hasText(elementName, "Element has no name");
            return elementName.endsWith(getResponseSuffix())
                    || (getRequestSuffix().isEmpty() ? true : elementName.endsWith(getRequestSuffix()))
                    || elementName.endsWith(getFaultSuffix());
        }
        return false;
    }

    protected boolean isMessageElement0(Element element) {
        return "element".equals(element.getLocalName())
                && "http://www.w3.org/2001/XMLSchema".equals(element.getNamespaceURI());
    }
}

MySuffixBasedPortTypesProvider自定义类(为简便起见去除进口):

package hello;

public class MySuffixBasedPortTypesProvider extends SuffixBasedPortTypesProvider {

    private String requestSuffix = DEFAULT_REQUEST_SUFFIX;

    public String getRequestSuffix() {
        return requestSuffix;
    }

    public void setRequestSuffix(String requestSuffix) {
        this.requestSuffix = requestSuffix;
    }

    @Override
    protected String getOperationName(Message message) {
        String messageName = getMessageName(message);
        String result = null;
        if (messageName != null) {
            if (messageName.endsWith(getResponseSuffix())) {
                result = messageName.substring(0, messageName.length() - getResponseSuffix().length());
            } else if (messageName.endsWith(getFaultSuffix())) {
                result = messageName.substring(0, messageName.length() - getFaultSuffix().length());
            } else if (messageName.endsWith(getRequestSuffix())) {
                result = messageName.substring(0, messageName.length() - getRequestSuffix().length());
            }
        }
        return result;
    }

    @Override
    protected boolean isInputMessage(Message message) {
        String messageName = getMessageName(message);

        return messageName != null && !messageName.endsWith(getResponseSuffix());
    }

    private String getMessageName(Message message) {
        return message.getQName().getLocalPart();
    }

}

MyWsdl11Definition自定义类(基本上是默认的,只是上面的实例类的副本,进口简洁,删除):

package hello;

public class MyWsdl11Definition implements Wsdl11Definition, InitializingBean {

    private final InliningXsdSchemaTypesProvider typesProvider = new InliningXsdSchemaTypesProvider();

    private final SuffixBasedMessagesProvider messagesProvider = new MySuffixBasedMessagesProvider();

    private final SuffixBasedPortTypesProvider portTypesProvider = new MySuffixBasedPortTypesProvider();

    private final SoapProvider soapProvider = new SoapProvider();

    private final ProviderBasedWsdl4jDefinition delegate = new ProviderBasedWsdl4jDefinition();

    private String serviceName;

    public MyWsdl11Definition() {
        delegate.setTypesProvider(typesProvider);
        delegate.setMessagesProvider(messagesProvider);
        delegate.setPortTypesProvider(portTypesProvider);
        delegate.setBindingsProvider(soapProvider);
        delegate.setServicesProvider(soapProvider);
    }

    public void setTargetNamespace(String targetNamespace) {
        delegate.setTargetNamespace(targetNamespace);
    }

    public void setSchema(XsdSchema schema) {
        typesProvider.setSchema(schema);
    }

    public void setSchemaCollection(XsdSchemaCollection schemaCollection) {
        typesProvider.setSchemaCollection(schemaCollection);
    }

    public void setPortTypeName(String portTypeName) {
        portTypesProvider.setPortTypeName(portTypeName);
    }

    public void setRequestSuffix(String requestSuffix) {
        portTypesProvider.setRequestSuffix(requestSuffix);
        messagesProvider.setRequestSuffix(requestSuffix);
    }

    public void setResponseSuffix(String responseSuffix) {
        portTypesProvider.setResponseSuffix(responseSuffix);
        messagesProvider.setResponseSuffix(responseSuffix);
    }

    public void setFaultSuffix(String faultSuffix) {
        portTypesProvider.setFaultSuffix(faultSuffix);
        messagesProvider.setFaultSuffix(faultSuffix);
    }

    public void setCreateSoap11Binding(boolean createSoap11Binding) {
        soapProvider.setCreateSoap11Binding(createSoap11Binding);
    }

    public void setCreateSoap12Binding(boolean createSoap12Binding) {
        soapProvider.setCreateSoap12Binding(createSoap12Binding);
    }

    public void setSoapActions(Properties soapActions) {
        soapProvider.setSoapActions(soapActions);
    }

    public void setTransportUri(String transportUri) {
        soapProvider.setTransportUri(transportUri);
    }

    public void setLocationUri(String locationUri) {
        soapProvider.setLocationUri(locationUri);
    }

    public void setServiceName(String serviceName) {
        soapProvider.setServiceName(serviceName);
        this.serviceName = serviceName;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (!StringUtils.hasText(delegate.getTargetNamespace()) && typesProvider.getSchemaCollection() != null &&
                typesProvider.getSchemaCollection().getXsdSchemas().length > 0) {
            XsdSchema schema = typesProvider.getSchemaCollection().getXsdSchemas()[0];
            setTargetNamespace(schema.getTargetNamespace());
        }
        if (!StringUtils.hasText(serviceName) && StringUtils.hasText(portTypesProvider.getPortTypeName())) {
            soapProvider.setServiceName(portTypesProvider.getPortTypeName() + "Service");
        }
        delegate.afterPropertiesSet();
    }

    @Override
    public Source getSource() {
        return delegate.getSource();
    }

}

此外,类的defaultWsdl11Definition方法WebServiceConfig将更改如下(使用上面的自定义):

@Bean(name = "countries")
public Wsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    MyWsdl11Definition wsdl11Definition = new MyWsdl11Definition();
    wsdl11Definition.setPortTypeName("CountriesPort");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setRequestSuffix("");
    wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
    wsdl11Definition.setSchema(countriesSchema);
    return wsdl11Definition;
}

注意wsdl11Definition.setRequestSuffix("");哪个有效地将后缀设置为空.

在此自定义之后,您可以更改XSD删除请求后缀,将生成新的GetCountry类,您需要手动删除以前存在的GetCountryRequest并修复上面提到的编译错误(测试和端点类,只是'忘记更新@PayloadRoot注释).

然后构建运行正常.运行Applicationmain,生成的WSDL将按要求包含:




  
  
    
  
  
    
  


希望能帮助到你.这是一个关于配置的约定大大提供的一个真实的例子,而在框架编写代码和添加自定义方面,框架中的一个小的无法预料的变化就意味着什么.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有