发现自己总是闭门造车,总是疏于整理与总结。下决心改变自己,从每件小事做起吧。共勉
?
最近做WebServices 比较多,和各种企业联调弄得楼主焦头烂额。其中,最郁闷的,还是与.net平台的对接。
?
楼主本地系统是Axis2 ,分别与Axis,Axis2与.net的接口来对接。
?
刚一开始采用的方案是基于采用本地发布的wsdl作为标准,使用Axis2工具生成Stub客户端来调用各企业接口。楼主一开始想当然的认为既然是发布的服务,应该遵守SOA的规范,那么通过生成的客户端,理应可以各种接口各种调。结果,残酷的事实证明,这样是行不通的。在采取客户端,调用Axis的服务时,发现了很尴尬的问题。使用本地的Stub,调用失败。
本地生成jibx Stub客户端方法如下:
?
?
注:需要配置%JAVA_HOME%
?
生成的客户端是在 tobacco.ecs.pub 下。
?
将生成的Stub客户端拷到项目目录下,使用stub客户端调用对方的方法时,错误如下:
?
at tobacco.ecs.pub.ECS_NAT_INF_DataRecvECS_NAT_INF_DataRecvSOAP12Port_http1Stub.receive(ECS_NAT_INF_DataRecvECS_NAT_INF_DataRecvSOAP12Port_http1Stub.java:371)
at tobacco.ecs.pub.StubTest.testReceive(StubTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
?
?
?经过分析,这个悲催的事情是因为命名空间发生的问题,我们就努力的统一命名空间,结果还是失败。
?
因为项目周期问题,楼主并没有在这一个问题上纠结下去,努力完成需求才是我们想要的。于是便采用了更加通用的方法,采用RPCclient,用invokeBlocking来调用,这次顺利成功。
?
至此,楼主本以为大功告成,Axis2与Axis顺利调通,哪知道,真正悲催的事情总是发生在最后。
?
在与两家企业顺利对接后,真正的boss,.net开发的服务接口找上门来了。使用RPCclient确实不能满足了。通过使用httplook抓取soap消息中,发现了问题。(这里吐槽一下,httplook真是神器啊。。。虽说好用,但是装上后机器变慢,卸载了又不能上网。。怨念)这边服务调用的时候,发送的request请求参数没有对应的名称,发送的request的OMElement参数都是arg0 arg1之流,到了那边,人家根本就不认,对方的Action也需要跟在命名空间后- -
?
这下可把楼主惹毛了,已经对接两家了,难不成还能因为一个.net平台难倒了?在不懈的努力下,终于发现,stub客户端中,是有拼接OMElement的方法的!灵机一动,我就打算自己拼接OMElement。
最终实现的代码如下:
/** * 根据传入的参数返回拼装好的 OMElement * @param omMap * @param nameSpace * @param action * @return */ public OMElement getOmElement(Map<String, String> omMap, String action) { SOAPFactory factory = OMAbstractFactory.getSOAP12Factory(); OMElement child; OMElement wrapper = factory.createOMElement(action, namespace, ""); Set<String> lableSet = omMap.keySet(); Iterator<String> it = lableSet.iterator(); while(it.hasNext()){ String lable = it.next(); child = factory.createOMElement(lable, namespace, ""); child.setText(omMap.get(lable)); wrapper.addChild(child); } return wrapper; } public String invoke(String action,OMElement wrapper) throws AxisFault { RPCServiceClient rpcClient = new RPCServiceClient(); Options options = rpcClient.getOptions(); EndpointReference targetEPR = new EndpointReference(endpoint); options.setTo(targetEPR); options.setAction(namespace + "/" + action); // 解决.net 调用java 调用不通时使用 // options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED,Boolean.FALSE); OMElement response = rpcClient.sendReceive(wrapper); Object[] objects = BeanUtil.deserialize(response, new Class[] { String.class }, new DefaultObjectSupplier()); return objects[0].toString(); }
?
其中,deserialize?是对response返回的消息进行反序列化,可以形成我们原来的返回消息格式
?
?经过三番五次的测试,.net和java纷纷落马~O~Ye~
?
楼主经验尚浅,说的肯定有很多不对或者不准确或者瞎掰的地方。只求将解决方案与大家共勉,希望大家不要吝啬,多提宝贵意见及问题。