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); }