xfire客户端连接cxf服务端完全解决!
背景:项目需求要求与一个外部接口做对接,对方的服务端是cxf,而项目组用的是xfire1.2.6,JDK1.5。 对方也不可能改他们的服务端为xfire版本。 问题:因为历史原因,本项目是运行了多年的老系统,jdk1.5的环境,客户不可能因为一个接口就升级jdk到1.6,而且老系统里有很多接口都是在xfire上开发的,也不可能因为cxf来一次大改动,还不包括测试。 执行:用xfire静态模式来调用cxf服务端,报错,有注解的错,jar兼容的问题,还有一些网上讨论的问题。花了一周时间做了各自修改测试(配置上的),都无法完美解决xfire客户端调用cxf服务端的问题。 其中甚至包括把cxf生成的对应客户端包括环境jar包打成一个jar包来测试(目的是不影响生产环境其他jar,可以不用为升级jar或兼容问题操心了), 但是测试发现,这种打jar包的方法只能在jdk1.6下执行,在jdk1.5下就报找不到rt.jar下的 java.lang.NoClassDefFoundError: javax/xml/ws/Service 初衷是想不伤筋动骨下完成这个接口的对接。 看来不做点小手术是不行的了,好吧,开始改xfire源码。 cxf就是在xfire基础上升级而来的,cxf解决了xfire的很多缺陷,并且xfire停留在1.2.6版本上就再没更新了。 大趋势是cxf替换掉老掉牙的xfire,但你那注解式的开发貌似引出配置上很多问题,而且本人极度不习惯注解;而且cxf对soap是严格标准,对xfire很难容忍,xfire的一些元素命名格式不符合cxf的标准,导致xfire client to cxf无法成功。 那么开始从soap入手看看到底哪里不对了。 设置cxf服务端接口,支持打印请求和响应: 这个是我测试的接口文件和接口方法 @WebService public @WebResult String sayHello(String name,String agr); } 先来看cxf客户端调用的soap请求和服务端的响应: 2013-1-23 13:07:17 org.apache.cxf.interceptor.LoggingInInterceptor logging Payload: http://schemas.xmlsoap.org/soap/envelope/"><<BR>soap:Body>doony28http://test.com/">doony28 再来看xfire的请求: Payload: http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="">http://www.w3.org/2001/XMLSchema-instance"> /">http://test.com"> doony 28 可以看到xfire对sayHello的参数,包了个“”的标签。 以及的也少了一个“/”, 那么是否能把soap改成和cxf一致就可以了呢。 一番调试,确定了soap生成的java类是“org.codehaus.xfire.service.binding.AbstractBinding”。 修改它,让它支持cxf,再测, yes,xfire可以了。 题外话,调试过程中,发现xfire确实存在不少优化及待改进的问题 ,下来有时间慢慢完善, 不想这么快就杀死xfire,系统还是存在很多外部调用方也是xfire的,我们升级成cxf,那估计他们要痛苦了。 这里附上xfire的动态客户端代码,方便测试: import java.net.HttpURLConnection; import java.net.URL; import org.codehaus.xfire.client.Client; import org.codehaus.xfire.transport.http.CommonsHttpMessageSender; public class Test { public static final String WebService_URL = "http://localhost:8083/WebService/HelloWorld?wsdl"; public static void main(String[] args) { Client client1 = null; try { URL _url = new URL(WebService_URL); HttpURLConnection httpConnection = (HttpURLConnection)_url.openConnection(); httpConnection.setReadTimeout(20000);//设置http连接的读超时,单位是毫秒 ? httpConnection.connect(); client1 = new Client(httpConnection.getInputStream(),null); client1.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT,String.valueOf( 20000 ));//设置发送的超时限制,单位是毫秒; ? client1.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE,"true"); ? client1.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE,"true"); Object[] strResult1 = null; // 如果接口有方法名,且需要带参数,则在 invoke注明,参数以Object[]数组形式 strResult1 = client1.invoke("sayHello",new Object[] {"doony","28"}); System.out.println("调接口返回xml格式-->" + strResult1[0]); } catch (Exception e) { e.printStackTrace(); } } }
xfire静态客户端这里就不列了,都能用。
转载请注明出处,谢谢! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |