cxf WebService设置wsdl中soapAction的值

用cxf开发一个WebService很简单,只需要下面几步:

1.定义接口

public interface HelloService {
    String hello();
}

2.实现

public class HelloServiceImpl implements HelloService {
    @Override
    public String hello() {
        return "hi,my name is gyoung ";
    }
}

3.用ServerFactoryBean生成服务

复制代码
    public static void main(String[] args) {
        HelloServiceImpl helloworldImpl = new HelloServiceImpl();
        //cxf发布服务的工厂bean
        ServerFactoryBean svrFactory = new ServerFactoryBean();
        //设置服务类
        svrFactory.setServiceClass(HelloService.class);
        //设置服务地址
        svrFactory.setAddress("http://localhost:9001/Hello");
        //设置服务bean
        svrFactory.setServiceBean(helloworldImpl);
        svrFactory.create();
    }
复制代码

这样,一个简单的HelloWorld服务便生成成功了。

但是,这样生成的服务有一个问题,wsdl中的soapAction属性是空的

复制代码
<wsdl:binding name="HelloServiceSoapBinding" type="tns:HelloServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="hello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
复制代码

这一段<soap:operation soapAction="" style="document"/>,如果是.net生成的服务,soapAction是有值的  

复制代码
<wsdl:binding name="WebService1Soap" type="tns:WebService1Soap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="HelloWorld">
<soap:operation soapAction="http://tempuri.org/HelloWorld" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
复制代码

查看了很久的源码,才发现,设置cxf设置soapAction是在org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean类中

它会去循环遍历serviceConfigurations,调用其getAction方法来获取action的值。但初始的serviceConfigurations只有DefaultServiceConfiguration和SoapBindingServiceConfiguration,这两个类都没有实现其基类AbstractServiceConfiguration中的getAction方法。所以getAction返回值是空,所以wsdl中的soapAction值也会是空。找到问题就好办了,我们在serviceConfigurations中增加一个config,在AbstractServiceConfiguration的众多子类中,我发现MethodNameSoapActionServiceConfiguration有继承getAction方法,所以我们只需要在生成服务的时候,增加一个MethodNameSoapActionServiceConfiguration

配置就行了。

复制代码
  public static void main(String[] args) {
        HelloServiceImpl helloworldImpl = new HelloServiceImpl();
        //cxf发布服务的工厂bean
        ServerFactoryBean svrFactory = new ServerFactoryBean();
        svrFactory.getServiceFactory().getConfigurations().add(new MethodNameSoapActionServiceConfiguration());
        //设置服务类
        svrFactory.setServiceClass(HelloService.class);
        //设置服务地址
        svrFactory.setAddress("http://localhost:9001/Hello");
        //设置服务bean
        svrFactory.setServiceBean(helloworldImpl);
        svrFactory.create();
    }
复制代码

最张生成的wsdl

复制代码
<wsdl:binding name="HelloServiceSoapBinding" type="tns:HelloServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="hello">
<soap:operation soapAction="hello" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
复制代码

当然,我们也可以自己继承AbstractServiceConfiguration来实现getAction方法。
转自:https://www.cnblogs.com/Gyoung/p/5469536.html

原文地址:https://www.cnblogs.com/liushui-sky/p/10831360.html