背景:对接oa系统,需要用webservice方式对接,对方提供了wsdl地址和对应文件,之后说要在请求头信息上添加对应的验证信息(非标准的验证,是自定义的头信息,服务端自己解析处理)。现场环境为内网环境,只能通过vpn访问,并且测试的时候不能频繁发增量包,因为项目启动时间比较长,耽误现场实施配置东西。
首先对接接口
第一步:反向生成客户端(这应该是对接webservice接口最简单的方式了)关于webservice基本知识强烈建议首先参考:
webservice基础补强!!!
反向生成客户端,首先看看项目用的哪个版本的jdk,然后到jdk bin界面删除原路径后输入cmd回车后即可
对应命令为
wsimport -p cn.cad.mobile -s . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
命令解析:
-p 后为你生成文件的src下的包名
-s 后要把文件生成在哪个地方,“.”即为当前路径。
最后部分为给出的wsdl链接,或者为wsdl文件(访问这个链接后右键另存为,然后改一下后缀即可)
这样客户端就生成了,具体如何使用,参考上方的链接。
第二步:测试联调,本地测试需要使用soapui测试工具
首先生成客户端,点击soap,然后将wsdl链接输入点ok即可。
然后生成服务端
相当于本地已经有了对应的服务端,访问对应链接发现没有问题
展示出对应的wsdl文件则没有问题,第二次打开的时候需要右键服务端开启。
自己写的测试类能返回200即可,说明接口能通
jar包测试
将自己写完的测试类打成jar包后,在现场进行测试即,这样既能测试接口是否通了,也能不影响试试人员调试现场问题,不用频繁换包。
javaproject工程打jar包参考
打jar包,并运行
运行指定main方法
补充生成客户端并补充头部的方法,都是增加拦截的方法(注释的上下部分),
package com.limy.test.common.tt;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.limy.test.common.AddHeaderInterceptor;
import com.limy.test.common.WsUtils;
public class Test {
public static void main(String[] args) {
// JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// // 记录入站消息
// factory.getInInterceptors().add(new LoggingInInterceptor());
// // 记录出站消息
// factory.getOutInterceptors().add(new LoggingOutInterceptor());
// // 添加消息头验证信息。如果服务端要求验证用户密码,请加入此段代码
//
// factory.getOutInterceptors().add(new AddHeaderInterceptor("123", "456"));
// factory.setServiceClass(MobileCodeWSSoap.class);
// factory.setAddress("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");
// // 使用MTOM编码处理消息。如果需要在消息中传输文档附件等二进制内容,请加入此段代码
// // Map props = new HashMap();
// // props.put("mtom-enabled", Boolean.TRUE);
// // factory.setProperties(props);
//
// // 创建服务代理并返回
// MobileCodeWSSoap ws = (MobileCodeWSSoap) factory.create();
MobileCodeWSSoap ws = WsUtils.getProxyEkPws();
String resu = ws.getMobileCodeInfo("15733883789", "");
System.out.println(resu);
// URL wsdlLocation;
// MobileCodeWSSoap ws = null;
// try {
// wsdlLocation = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");
// ws = (MobileCodeWSSoap) new MobileCodeWS(wsdlLocation).getMobileCodeWSSoap();
// Client client = ClientProxy.getClient(ws);
// client.getInInterceptors().add(new LoggingInInterceptor());
// client.getOutInterceptors().add(new LoggingOutInterceptor());
// client.getOutInterceptors().add(new AddHeaderInterceptor("456", "484565"));
//
// } catch (MalformedURLException e) {
// e.printStackTrace();
// }
// System.out.println(ws.getMobileCodeInfo("15733883789", ""));;
}
}
最后有一个增加头信息验证的部分,因为不是标准的头信息验证,需要用稍微特殊的方式增加对应头信息,下面是具体的监听代码。
当时遇见的问题是子节点不想有对应的命名空间部分,上面的代码无法实现,所以用了下面未注释的。
package com.limy.test.common; import java.util.List; import javax.xml.namespace.QName; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.headers.Header; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.w3c.dom.Document; import org.w3c.dom.Element; public class AddHeaderInterceptor extends AbstractPhaseInterceptor{ private String user; private String password; public AddHeaderInterceptor(String user, String password) { super(Phase.PREPARE_SEND); // 发送SOAP消息之前调用拦截器 this.user=user; this.password=password; } public void handleMessage(SoapMessage message) throws Fault { String namespace = "http://sys.webservice.client"; //命名空间 String prefix = "tns"; //前缀 List headers=message.getHeaders(); // try { // // SOAPElement requestSOAPHeaderElm = SOAPFactory.newInstance().createElement("RequestSOAPHeader",prefix,namespace); // // SOAPElement userElm = SOAPFactory.newInstance().createElement("user",prefix,namespace); //user标签 // SOAPElement posswordElm = SOAPFactory.newInstance().createElement("possword",prefix,namespace); //possword标签 // userElm.addTextNode(user); // posswordElm.addTextNode(password); // // requestSOAPHeaderElm.addChildElement(userElm); // requestSOAPHeaderElm.addChildElement(posswordElm); // // SoapHeader hh = new SoapHeader(new QName("RequestSOAPHeader"), requestSOAPHeaderElm); // headers.add(hh); // // } catch (SOAPException e) { // e.printStackTrace(); // } Document doc=DOMUtils.createDocument(); Element ele = doc.createElementNS(namespace, "RequestSOAPHeader"); ele.setPrefix(prefix); Element idElement=doc.createElementNS(namespace,"user"); idElement.setPrefix(prefix); idElement.setTextContent(user); Element passElement=doc.createElementNS(namespace,"password"); passElement.setPrefix(prefix); passElement.setTextContent(password); ele.appendChild(idElement); ele.appendChild(passElement); headers.add(new Header(new QName(namespace,"RequestSOAPHeader",prefix),ele)); } }
致此结束。
从这一顿操作中,感觉猜了无数的坑,最后还是完成了,而且最后用的另一种打jar包的方法(自定义.MF文件)
重新又理解了最初写helloword并让黑白框显示出helloword的过程,挺好。
最后是webservice需要的jar包为(不包括gson的)



