cxf WebService设置wsdl中soapAction的值

时间:2023-03-08 16:52:02

用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类中

cxf WebService设置wsdl中soapAction的值

它会去循环遍历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方法。