歡迎來到:http://observer.blog.51cto.com
webservcie是可以跨語言跨平台開發的一種技術,各種電腦語言都可以搭建伺服器,同時各種電腦語言也可以開發用戶端。只要有伺服器,不管是用java還是C++抑或是php搭建的,其他語言都可以根據其開放的wsdl開發好用戶端,然後調用其方法就像調用本地本項目的方法一樣。本文使用js開發用戶端,例子依賴於上一篇文章:CXF搭建webService伺服器;如果有不明白的可以先看此文章再看本文。
使用js編寫webservice用戶端,有很多方法,使用CXF內建wsdl2js命令也是可以的,但是這個命令出來的js代碼簡直不能接受,太亂了,一大陀代碼不好控制,還是算了吧!這裡介紹的是自己使用js編寫用戶端的方法。
第一步:編寫xml
根據發布的wsdl編寫xml。這裡就出現問題了,要是對wsdl不瞭解的,怎麼編寫呢?而且還容易出錯,到時候簡直不知道是自己xml錯了還是js代碼錯了。呵呵,這裡介紹一個很好用的實現web service和web service的功能/負載/符合性測試的工具:soapui。此工具可以根據wsdl產生xml,然後測試。
下載soapui因為檔案太大,我就上傳liunx的行了,windows的朋友盡可以自己上網搜一下。):soapui-4.5.1_for_liunx
下載後解壓,進入soapui-4.5.1/bin後運行soapui.shwindows的朋友自行運行安裝好的soapui)如:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1134213207-0.png" title="webServicejs用戶端1.png" />
右鍵Projects——>new soapui project,在新出現的視窗project name可以自訂)與initial wsdl/wadl一欄中都填上wsdl如:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1134211010-1.png" title="webServicejs用戶端2.png" />
點擊ok就可以在projects下看到已將串連的webservice,雙擊對應的webservcie的方法下面的request 1就會看到soapui根據wsdl自動給我們產生的xml,在xml裡面找到自己定義的方法的變數名,填上變數,點擊request 1視窗左上方的運行按鈕進行測試,能夠得到結果就證明webservice測試通過,如我的測試如:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/1134211C0-2.png" title="webServicejs用戶端3.png" />
第二步:編寫js代碼
首先擷取HTTP協議的安全的訪問對象,然後發送請求,上代碼:
function serviceHelloWrod() { var serviceWsdl = 'http://127.0.0.1:8080/webServiceCXF/services/Service?wsdl'; //串連webservice的wsdl var serviceUrl = 'http://www.observer.com/service'; //自己定義的url,這個值就是伺服器端,定義介面時的targetNamespace //因為伺服器一旦定義運行,serviceWsdl跟serviceUrl就不會輕易改變,所以這裡將這兩個值定義在js檔案中 function getXMLRequester() {//此方法擷取對HTTP協議的安全的訪問的XMLHttpRequest對象 var xmlhttp_request = false; try { if (window.ActiveXObject) { xmlhttp_request = new ActiveXObject('Microsoft.XMLHTTP'); //在 IE 5 和 IE 6 中,必須使用特定於 IE 的 ActiveXObject() 建構函式 } else if (window.XMLHttpRequest) { xmlhttp_request = new XMLHttpRequest(); if (xmlhttp_request.overrideMimeType) { xmlhttp_request.overrideMimeType('text/xml'); } } } catch (e) { xmlhttp_request = false; alert('Sorry your browser version is too low, please update after use.'); } return xmlhttp_request; }; var xmlhttp = getXMLRequester(); function requestByPost(data) {//向webservice發送請求,得到返回的xml,然後解析xml得到傳回值 var URL = serviceWsdl; xmlhttp.open('POST', URL, false); xmlhttp.setRequestHeader('Content-Type', 'text/xml;charset=utf-8'); xmlhttp.setRequestHeader('SOAPAction', 'http://dao.wfservice.ws.emolay.com'); xmlhttp.send(data);//發送請求 var str = xmlhttp.responseText;//得到反饋的xml var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');//解析xml var result = xmlDoc.getElementsByTagName('result'); return result; }; function getGradeName(toid) { //編輯發送請求的xmldata變數),然後調用requestByPost方法請求webservice,這裡的xml完全可以使用soapui自動產生 var data = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="' + serviceUrl + '">'; data += '<soapenv:Header/>'; data += '<soapenv:Body>'; data += '<ser:getGradeName>'; data += '<toid>' + toid + '</toid>'; data += '</ser:getGradeName>'; data += '</soapenv:Body>'; data += '</soapenv:Envelope>'; var result = requestByPost(data); var str = []; for ( var i = 0; i < result.length; i=i+1) { str.push(result[i].firstChild.nodeValue); //因為webservice返還之不一定只是一個string,也可能是一個數組等等,所以xml標籤中不一定只有一個結果, //所以必須一個一個解析出來,然後拿到裡面的值。當然,如果真正確定了伺服器的傳回值個數,也可以將其固定起來 } return str; }; function getTest(toid){ //串連webservice return "test:"+toid; } function getMeans(means){//根據所給的參數返回方法 if(means=="getGradeName"){ return getGradeName; }else if(means=="getTest"){ return getTest; }else{ return null; } } return getMeans;}
到這裡,用戶端已經開發完成,以上技術上的問題就不多說了,代碼中已經的注釋得很清楚,如果想看更詳細的可以下載附件,這裡需要說一下設計:
首先,用戶端的js代碼使用的是閉包closure)編寫的,可移植性強,只要保證調用頁面沒有重複的serviceHelloWrod方法就可以像組件一樣拿去使用,不用擔心因為裡面的變數或者方法有重複而使js出錯。
其次,該用戶端組建模仿java中的映射,初始化方法之後會返回getMeans方法,此方法可以根據傳給它的參數返回一個webservcie串連的方法,讓調用者調用,如果沒有這個方法,則返回null,調用失敗。就像java中的映射一樣,你不需要知道這個方法是什麼,只要你知道webservice中有這個方法,你就可以根據一個字串得到這個方法,然後傳參調用它。此設計同時也易於擴充,如果webservice中添加了方法,比如說以上的添加了getTest方法,可以直接在js中添加function getTest(toid),然後在getMeans中添加可以返回的判斷即可。
第三步:應用用戶端
初始化用戶端,然後返回相應的方法,然後調用,如在html中可以這樣調用:
<script type="text/javascript"> var toid = 123; var means = serviceHelloWrod();//初始化 var str = means("getGradeName")(toid);//調用方法</script>
我的應用程式如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <script src=\'#\'" /service.js" type="text/javascript"></script> <script type="text/javascript"> function runServiceC(showjs){ var toid = 123; var means = serviceHelloWrod();//初始化 var str = means("getGradeName")(toid);//調用方法 document.getElementById(showjs).innerHTML = str; }; </script> <title>webServiceClientJs</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <div align="center"> <p id="showjs1"></p> </div> <div align="center"> show Service : <font id="showjs2">run before</font> <br /> <button type="button" 運行service用戶端 </button> <button type="button" onclick="(function(){document.getElementById('showjs2').innerHTML = 'run before';})();"> 還原show Service </button> </div> </body> <script type="text/javascript"> //直接定義一個沒有名字的方法,然後馬上運行 (function() { runServiceC("showjs1"); })();</script></html>
(非常抱歉的說,上面的html代碼放上去發布後總是顯示亂代碼,看不懂的朋友可以下載附件看)這裡的toid等需要動態產生的參數,可以根據jsp或者php等其他動態建站語言產生,最後想要怎樣應用,應用成怎麼樣就看自己的具體案例具體分析了。
到這裡,js的webservice用戶端的設計開發與應用已經講完,附上項目,如果對java的webservice感興趣,可以看看這篇文章: java中webservcie用戶端的設計開發與應用
後面會繼續放上關於技術與設計方面的文章,期待您的關注,謝謝。
本文出自 “觀察者*奔放” 部落格,請務必保留此出處http://observer.blog.51cto.com/4267416/1244274