cxf WebService設定wsdl中soapAction的值

Gyoung發表於2016-05-07

用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方法。

 

相關文章