SOAP & WSDL
- SOAP是一种交换数据的协议规范,用于规范服务端和客户端之间数据传输的规则。
- SOAP是基于HTTP协议进行传输,说白点,用SOAP协议写好的xml信息放在HTTP协议的请求体中发送到服务器或客户諯。
请求: POST /stockquote.asmx HTTP/1.1 Host: www.webservicex.net Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://www.webserviceX.NET/GetQuote" <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetQuote xmlns="http://www.webserviceX.NET/"> <symbol>string</symbol> </GetQuote> </soap:Body> </soap:Envelope>
响应: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetQuoteResponse xmlns="http://www.webserviceX.NET/"> <GetQuoteResult>string</GetQuoteResult> </GetQuoteResponse> </soap:Body> </soap:Envelope>
- WSDL,跟SOAP一点关系也没有,它只是一个描述服务的xml文件,它只有两个做用:一是让开发人员看,二是让第三方框架生成代码或动态调用。
调用WS
客户端调用WS的方式有哪几种:html
- 客户端硬编程方式
- ajax调用js+xml方式
- url connection方式
- 生成客户端代码方式(wsimport/wsdl2java等),如使用axis二、cxf等框架。
客户端编程方式
须要三个元素:java
1.javax.xml.ws.Service类 2.javax.xml.namespace.QName类 3.用wsimport生成的一个service接口。android
public class App { public static void main(String[] args) throws Exception { URL wsdlUrl = new URL("http://192.168.1.100:6789/hello?wsdl"); Service s = Service.create(wsdlUrl, new QName("http://ws.itcast.cn/","HelloServiceService")); HelloService hs = s.getPort(new QName("http://ws.itcast.cn/","HelloServicePort"), HelloService.class); String ret = hs.sayHello("zhangsan"); System.out.println(ret); } }
其中 HelloService 是用 wsimport 生成的一个接口。web
ajax 方式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>经过ajax调用WebService服务</title> <script> var xhr = new ActiveXObject("Microsoft.XMLHTTP"); function sendMsg(){ var name = document.getElementById('name').value; //服务的地址 var wsUrl = 'http://192.168.1.100:6789/hello'; //请求体 var soap = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ws.itcast.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' + ' <soapenv:Body> <q0:sayHello><arg0>'+name+'</arg0> </q0:sayHello> </soapenv:Body> </soapenv:Envelope>'; //打开链接 xhr.open('POST',wsUrl,true); //从新设置请求头 xhr.setRequestHeader("Content-Type","text/xml;charset=UTF-8"); //设置回调函数 xhr.onreadystatechange = _back; //发送请求 xhr.send(soap); } function _back(){ if(xhr.readyState == 4){ if(xhr.status == 200){ //alert('调用Webservice成功了'); var ret = xhr.responseXML; var msg = ret.getElementsByTagName('return')[0]; document.getElementById('showInfo').innerHTML = msg.text; //alert(msg.text); } } } </script> </head> <body> <input type="button" value="发送SOAP请求" onclick="sendMsg();"> <input type="text" id="name"> <div id="showInfo"> </div> </body> </html>
用jQuery如何开发????ajax
?????
url connection 方式
据说主要用于android开发....apache
public class App { public static void main(String[] args) throws Exception { //服务的地址 URL wsUrl = new URL("http://192.168.1.100:6789/hello"); HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8"); OutputStream os = conn.getOutputStream(); //请求体 String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://ws.itcast.cn/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<soapenv:Body> <q0:sayHello><arg0>aaa</arg0> </q0:sayHello> </soapenv:Body> </soapenv:Envelope>"; os.write(soap.getBytes()); InputStream is = conn.getInputStream(); byte[] b = new byte[1024]; int len = 0; String s = ""; while((len = is.read(b)) != -1){ String ss = new String(b,0,len,"UTF-8"); s += ss; } System.out.println(s); is.close(); os.close(); conn.disconnect(); } }
axis2
语法
wsdl2java 语法: wsdl2java 用于根据WSDL生成相应的服务端和客户端代码的生成工具。 命令行格式为:WSDL2Java [options] -uri <url or path> : A url or path to a WSDL 例如: wsdl2java -uri http://localhost:8080/cxfService_0617/services/Hellows?wsdl -s -o build\client 其中经常使用的options具体以下: -o <path> : 指定生成代码的输出路径 -a : 生成异步模式的代码 -s : 生成同步模式的代码 -p <pkg> : 指定代码的package名称 -l <languange> : 使用的语言(Java/C) 默认是java -t : 为代码生成测试用例 -ss : 生成服务端代码 默认不生成 -sd : 生成服务描述文件 services.xml,仅与-ss一同使用 -d <databinding> : 指定databingding,例如,adb,xmlbean,jibx,jaxme and jaxbri -g : 生成服务端和客户端的代码 -pn <port_name> : 当WSDL中有多个port时,指定其中一个port -sn <serv_name> : 选择WSDL中的一个service -u : 展开data-binding的类 -r <path> : 为代码生成指定一个repository -ssi : 为服务端实现代码生成接口类 -S : 为生成的源码指定存储路径 -R : 为生成的resources指定存储路径 –noBuildXML : 输出中不生成build.xml文件 –noWSDL : 在resources目录中不生成WSDL文件 –noMessageReceiver : 不生成MessageReceiver类
客户端调用
public class App { public static void main( String[] args ) { try { StockQuoteStub.GetQuote quote = new StockQuoteStub.GetQuote(); quote.setSymbol("string"); StockQuoteStub stub = new StockQuoteStub(); StockQuoteStub.GetQuoteResponse response = stub.getQuote(quote); String result = response.getGetQuoteResult(); System.out.println(result); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
项目实战:编程
public String getYinHaiYZM(String nameURI, String userName, String passWord, String jyyzm, String jylsh1, String jybh) { try { YinHaiBusinessStub stub = new YinHaiBusinessStub(); ServiceClient serviceClient = stub._getServiceClient(); serviceClient.addHeader(AddSoapHeaderTecsun.getSOAPHeaderBlock( nameURI, userName, passWord, jyyzm, jylsh1, jybh)); YinHaiBusinessStub.GetJylsh jylsh = new YinHaiBusinessStub.GetJylsh(); jylsh.setInputxml(AddSoapHeaderTecsun.getInputxml() + "<input></input>"); YinHaiBusinessStub.GetJylshE jylshe = new YinHaiBusinessStub.GetJylshE(); jylshe.setGetJylsh(jylsh); YinHaiBusinessStub.GetJylshResponse response = stub .getJylsh(jylshe).getGetJylshResponse(); String return_value = response.get_return(); return return_value; } catch (AxisFault e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } return null; } public static SOAPHeaderBlock getSOAPHeaderBlock(String nameURI, String userName, String passWord, String jyyzm, String jylsh, String jybh) { // 获取建立工厂�? OMFactory oMFactory = OMAbstractFactory.getOMFactory(); SOAPFactory sOAPFactory = OMAbstractFactory.getSOAP11Factory(); // 利用工厂,建立命名空间和消息头�?? OMNamespace oMNamespace = oMFactory.createOMNamespace(nameURI, "in"); SOAPHeaderBlock soapHeader = sOAPFactory.createSOAPHeaderBlock( "system", oMNamespace); SOAPHeaderBlock name = sOAPFactory.createSOAPHeaderBlock("userName", null); name.addChild(sOAPFactory.createOMText(userName)); SOAPHeaderBlock pass = sOAPFactory.createSOAPHeaderBlock("passWord", null); pass.addChild(sOAPFactory.createOMText(passWord)); SOAPHeaderBlock lsh = sOAPFactory.createSOAPHeaderBlock("jylsh", null); lsh.addChild(sOAPFactory.createOMText(jylsh)); SOAPHeaderBlock yzm = sOAPFactory.createSOAPHeaderBlock("jyyzm", null); yzm.addChild(sOAPFactory.createOMText(jyyzm)); SOAPHeaderBlock bh = sOAPFactory.createSOAPHeaderBlock("jybh", null); bh.addChild(sOAPFactory.createOMText(jybh)); soapHeader.addChild(name); soapHeader.addChild(pass); soapHeader.addChild(yzm); soapHeader.addChild(lsh); soapHeader.addChild(bh); return soapHeader; }
客户端调用总结:服务器
- wsdl2java 生成客户端
- 实例化 stub类,并调用其中的方法(stub类封装了大量的类和方法,如返回值等也封装成了一个类,调用此类中的方法便可以获得返回值)
cxf
wsdl2java 语法: wsdl2java -p com.tecsun.ws -d e:\temp\src -all xx.wsdl
参考:CXF - WSDL to Java,wsdl2java & wsimport 区别session
关于wsdl的解释
xml-ws-wsdl文件详细解释:app
xml-ws-wsdl文件详细解释2:
xml-ws-wsdl-cxf-调用详解:
客户端代码
- 依赖:
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency>
- JaxWsDynamicClientFactory使用:
public Result commonWithPage(String jybh,String aac002,String aac003,String yac005, String isfrom, int pageNo, int pageSize,Class clazz) throws Exception{ JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance(); Client c = factory.createClient(YINHAI_URL); HTTPConduit http =(HTTPConduit) c.getConduit(); HTTPClientPolicy hcp = new HTTPClientPolicy(); hcp.setConnectionTimeout(200000); hcp.setReceiveTimeout(200000); http.setClient(hcp); c.getOutInterceptors().add(new AddSoapHeader2(Constants.YINHAI_NAMESPACE, USER, PASSWORD, "", "", jybh)); String inputXml = "<input><aac002>" + aac002 + "</aac002><aac003>" + aac003 + "</aac003>" + "<yac005>" + yac005 + "</yac005><isfrom>" + converToNum(isfrom) + "</isfrom>" + "<startrow>" + (pageNo > 1 ? ((pageNo-1)*pageSize)+1 : 1) + "</startrow>" + "<endrow>" + (pageNo*pageSize) + "</endrow></input>"; System.out.println("imputXml:"+inputXml); Object[] obj = c.invoke("callBusiness",inputXml); String outputXML = ""; if(obj != null){ outputXML = (String)obj[0]; } System.out.println("==commonWithPage()中的outputXML====== start :"); System.out.println(outputXML); System.out.println("===commonWithPage()中的outputXMLL end===="); return XMLUtils.parseXml2Result(outputXML, clazz); }
注:YinHaiURL=http://10.131.134.1:7011/jypt/services/yinHaiBusiness?wsdl
设置SOAP请求头:
package com.tecsun.sisp.iface.outerface.egsec.session; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Created by Administrator on 2016/3/23. */ public class AddSoapHeader2 extends AbstractSoapInterceptor { private String nameURI; private String userName; private String passWord; private String jyyzm; private String jylsh; private String jybh; private String fwlsh; private String nbffyzm; private String fwdysxh; public AddSoapHeader2() { super("write"); } /** * 添加头信息 * @param nameURI URL * @param userName 用户名 * @param passWord 密码 * @param jyyzm 交易验证码 * @param jylsh 流水号 * @param jybh 交易编号 */ public AddSoapHeader2(String nameURI, String userName, String passWord, String jyyzm, String jylsh, String jybh) { super("write"); this.nameURI = nameURI; this.userName = userName; this.passWord = passWord; this.jyyzm = jyyzm; this.jylsh = jylsh; this.jybh = jybh; } public void handleMessage(SoapMessage message) throws Fault { QName qname = new QName("RequestSOAPHeader"); Document doc = DOMUtils.createDocument(); Element el_username = doc.createElement("userName"); el_username.setTextContent(this.userName); Element el_password = doc.createElement("passWord"); el_password.setTextContent(this.passWord); Element el_jylsh = doc.createElement("jylsh"); el_jylsh.setTextContent(this.jylsh); Element el_jyyzm = doc.createElement("jyyzm"); el_jyyzm.setTextContent(this.jyyzm); Element el_jybh = doc.createElement("jybh"); el_jybh.setTextContent(this.jybh); Element el_fwlsh = doc.createElement("fwlsh"); el_fwlsh.setTextContent(this.fwlsh); Element el_nbffyzm = doc.createElement("nbffyzm"); el_nbffyzm.setTextContent(this.nbffyzm); Element el_fwdysxh = doc.createElement("fwdysxh"); el_fwdysxh.setTextContent(this.fwdysxh); Element root = doc.createElementNS(this.nameURI, "in:system"); root.appendChild(el_username); root.appendChild(el_password); root.appendChild(el_jylsh); root.appendChild(el_jyyzm); root.appendChild(el_jybh); root.appendChild(el_fwlsh); root.appendChild(el_nbffyzm); root.appendChild(el_fwdysxh); SoapHeader head = new SoapHeader(qname, root); List headers = message.getHeaders(); headers.add(head); System.out.println(">>>>>添加header<<<<<<<"); } }
- 本地客户端的使用
public static void main(String[] args) { StockQuote stockQuote = new StockQuote(); StockQuoteSoap stockQuoteSoap = stockQuote.getStockQuoteSoap(); String result = stockQuoteSoap.getQuote("string"); System.out.println(result); }