1 制作返回值为复杂对象的服务的客户端
这种情况下最简单的方法就是用wsdl2java来生成客户端了,但是我又不想为这一个接口单独写一个客户端调用方法,
所以我把生成代码中的返回值类型的定义文件摘了出来写到客户端接口里,这样就不用在另写调用的代码。
用wsdl2java生成的方法如下:
C:\Users\changyf>E:\工作用文件夹名字起得长才显目懂得吗\java\apache-cxf-2.4.2\apa
che-cxf-2.4.2\bin\wsdl2java.bat -d f:\cnm -client http://localhost:8080/TsbWebSe
rvice/Tsb?wsdl
如果配过cxf_home的话则直接写wsdl2java就行,另外输入参数-p即可查看其他所有参数
2 动态调用服务的方法
JaxWsDynamicClientFactory testFb = JaxWsDynamicClientFactory.newInstance();
org.apache.cxf.endpoint.Client client = testFb.createClient("http://localhost:8080/TsbWebService/Tsb?wsdl");
client.getOutInterceptors().add(new AddPptSoapHeader());
String s = (String)client.invoke("cnm", "test");
3 对于wsdl的地址
最后要说的是我依然没有搞清楚的一个问题,对于wsdl的地址(例http://localhost:8080/TsbWebService/Tsb?wsdl)
中有时加上?wsdl会出现调用失败,有时变成大写?WSDL会调用失败。当然这有的是经过MB的中转有的是通过.NET平台的调用,再或者不同webservice架构之间调用,总之还有很多问题需要再研究一下。
4 设置服务超时
public ICyfClient returnCyfClient(){
JaxWsProxyFactoryBean proxyFb = new JaxWsProxyFactoryBean();
proxyFb.setAddress("http://localhost:8080/TsbWebService/Cyf?wsdl");
proxyFb.setServiceClass(ICyfClient.class);
ICyfClient client = (ICyfClient)proxyFb.create();
// 设置服务对象的代理
org.apache.cxf.endpoint.Client proxy = ClientProxy.getClient(client);
setTimeOut(proxy);
return client;
}
private void setTimeOut(Client proxy){
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
// 设置连接超时
policy.setConnectionTimeout(TsbWsConstant.SERVICE_REQUEST_TIMEOUT);
// 设置请求超时
policy.setReceiveTimeout(TsbWsConstant.SERVICE_REQUEST_TIMEOUT);
conduit.setClient(policy);
}
5 关于识别wcf生成的wsdl
在某次调用一个wcf生成的wsdl文件时,总是不能成功,后来发现这个生成的wsdl跟之前见过其他的wsdl不太一样,先看一下这个wsdl中的prottype节点
<wsdl:portType name="lms">
<wsdl:operation name="UpdateUserInfoToLMS">
<wsdl:input wsaw:Action="http://tempuri.org/lms/UpdateUserInfoToLMS" message="tns:UpdateUserInfoToLMS_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/lms/UpdateUserInfoToLMSResponse" message="tns:UpdateUserInfoToLMS_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
在operation节点里面的<wsdl:input>和<wsdl:output>节点就表示着这个服务采用标准的请求-响应模式,在input和output节点中均有Action属性,这个Action属性代表了调用服务过程中,往来的消息(可能从Server到Client,也可能相反)各自代表了怎么样的“动作”。例如UpdateUserInfoToLMS这个操作,当一个发送到服务端的消息的首部设置有Action="http://tempuri.org/lms/UpdateUserInfoToLMS"的时候,WCF知道如果把该消息分发到相应的服务操作中,这也就说明了,这个Action首部可以被用于消息筛选。而作为响应的消息,它的Action首部的值被默认设置为:请求消息的Action首部值 + "Response"。
作为客户端我们接收这种服务的时候就需要在我们的接口上再添加注解指定这个Action,不然在发起请求soap时是不能找到真正的服务处理。所以我们的客户端的接口做如下修改:
public @WebResult(name = "UpdateUserInfoToLMSResult", targetNamespace = "http://tempuri.org/")
@Action(input="http://tempuri.org/lms/UpdateUserInfoToLMS",output="http://tempuri.org/lms/UpdateUserInfoToLMSResponse")
String UpdateUserInfoToLMS(
@WebParam(name = "strParams", targetNamespace = "http://tempuri.org/") String strParams);
其中注解@Action中的input和output需要和服务端的wsdl保持一致。