JAX_WS 2.2 规范的webservices客户端实现(Axis2,Cxf)
为了对接之前老版本的接口,折腾了好几个小时.
主要是目前我的程序采用的是axis2的jax_rpc方式发布webservices服务,用这种服务的客户端,去调用老版本的jax_ws 2.2的接口,会报Runtime空指针。
于是采用cxf,使用了cxf3.0.3(当前版本) 的wsdl2java工具,生成了客户端的代码:
wsdl2java ****?wsdl
写了一个测试类来调用:
package com.test; import java.net.MalformedURLException; import java.net.URL; /** * Created by wang on 15-1-27. */ public class Test { public static void main(String[] args) { URL wsdlLocation= null; try { wsdlLocation = new URL("***"); NocPacket nocPacket=new NocPacket(); nocPacket.setPayload("lasdfsfsdf"); EventForwarderService service=new EventForwarderService(wsdlLocation); EventForwarderInterface ss=service.getEventForwarderPort(); FeedResult result=ss.send(nocPacket); System.out.println(result.getResultDesc()); } catch (MalformedURLException e) { e.printStackTrace(); } } }
测试没问题,能够调用ok。
不过此处有一个问题。如果用jdk7的话,它的包里面已经有jax_ws 2.2 的实现构造方法,不会报问题。但是如果用jdk6, cxf生成的代码中,继承的Services.class少一个带Feature的构造方法,jdk6默认只有一个构造。这里说的比较含糊,看一下jdk源码可以看出来问题的。用jdk6的话,要引入cxf的一个包:geronimo-jaxws_2.2_spec-1.2.jar 。cxf的压缩包自带的有。
然后要配置下包的加载顺序,引入的geronimo-jaxws_2.2_spec-1.2包优先加载,其次是jdk。如果是eclipse,在环境路径中,修改一下顺序。如果是Idea,在module中,也调整一下顺序。这样,在jdk6下也可以正常使用。
之所以没有采用cxf,是因为集成到axis2的环境中,包会冲突。
自身用的axis2,却用cxf的client,太坑。发现axis2也有wsdl2java的工具,果断用它来生成了客户端代码,这个生成的代码只有两个类,看上去很简洁:
wsdl2java -uri ***?wsdl -o src
配置一下生成代码的目录为src。
代码是生成了,但是调用代码却折磨了好一会儿,根据网上的代码,是不行的。所以这里分享一下,以免后人多走弯路。
package com.wang; import java.rmi.RemoteException; import org.apache.axis2.AxisFault; public class TestMain { public static void main(String[] args) { try { NocPacket nocPacket=new NocPacket(); nocPacket.setPayload("1232311"); String urlString="****"; EventForwarderServiceStub stub=new EventForwarderServiceStub(urlString); Send send=new Send(); send.setNocPacket(nocPacket); SendE sende=new SendE(); sende.setSend(send);; try { SendResponse response=stub.send(sende).getSendResponse(); FeedResult result=response.getResult(); System.out.println(result.getResultDesc()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (AxisFault e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
网上的代码,比如这里调用我需要的send方法的话,他们直接是用send方法。但是本人试验了很多次都不成功,必须中间经过SendE这个方法对象。不知道这个是不是axis2后来修改过。
如此折腾了很久,终于在工程中,只用axis2就完成了服务端和客户端的所有操作。