posts - 297,  comments - 1618,  trackbacks - 0
           

          說(shuō)明:該文為《JavaScript高級(jí)程序設(shè)計(jì)》第16章學(xué)習(xí)筆記。

           Web項(xiàng)目中,要實(shí)現(xiàn)客戶端與服務(wù)端的交互,可通過(guò)cookie、隱藏框架、HTTP請(qǐng)求、LiveConnect請(qǐng)求和智能HTTP請(qǐng)求等方式實(shí)現(xiàn),

          一.             cookie

           cookie是第一個(gè)JavaScript可以利用的客戶端-服務(wù)端之間的交互手段。瀏覽器向服務(wù)器發(fā)送請(qǐng)求時(shí),為這個(gè)服務(wù)器存儲(chǔ)的cookie會(huì)與其他信息一起發(fā)送到服務(wù)器。這使得JavaScript可以在客戶端設(shè)置一個(gè)cookie,之后服務(wù)器端就能夠讀取它了。

          1.    cookie的成分

                名稱——每一個(gè)cookie由一個(gè)唯一的名稱代表。這個(gè)名稱可以包含字母、數(shù)字和下劃線。不區(qū)分大小寫(xiě)。

                值——保存在cookie中的字符串值。這個(gè)值在存儲(chǔ)之前必須用encodeURIComponent()對(duì)其進(jìn)行編碼,以免丟失數(shù)據(jù)或占用了cookie。名稱和值加起來(lái)的字節(jié)數(shù)不能超過(guò)4095字節(jié),也就是4KB

                域——處于安全考慮,網(wǎng)站不能訪問(wèn)其他域創(chuàng)建的cookie。創(chuàng)建cookie后,域的信息會(huì)作為cookie的一部分存儲(chǔ)起來(lái)。不過(guò),雖然這不常見(jiàn),還是可以覆蓋這個(gè)設(shè)置以允許另一個(gè)網(wǎng)站訪問(wèn)這個(gè)cookie的。

                路徑——另一個(gè)cookie的安全特性,路徑限制了對(duì)Web服務(wù)器上的特定目錄的訪問(wèn)。例如,可指定cookie只能從http://www.wrox.com/books中訪問(wèn)。

                失效日期——確定cookie何時(shí)刪除。默認(rèn)情況下,關(guān)閉瀏覽器時(shí),即將cookie刪除,不過(guò)可以自己設(shè)置刪除時(shí)間。這個(gè)值是個(gè)GMT格式的日期(可以使用Date對(duì)象的toGMTString()方法),用于制定應(yīng)該刪除cookie的準(zhǔn)確時(shí)間。如果設(shè)置的日期是當(dāng)前日期以前的時(shí)間,則cookie被立刻刪除。

                 安全標(biāo)志——用于表示cookie是否只能從安全網(wǎng)站(使用SSLhttps協(xié)議的網(wǎng)站)中訪問(wèn)。可以將這個(gè)值設(shè)為true以加強(qiáng)保護(hù),進(jìn)而確保cookie不被其他網(wǎng)站訪問(wèn)。

          2.    其他安全限制

               i)每個(gè)域最多只能只能在一臺(tái)用戶的機(jī)器上存儲(chǔ)20個(gè)cookie

               ii)每個(gè)cookie的總尺寸不能超過(guò)4096字節(jié);

               iii)一臺(tái)用戶的機(jī)器上的cookie總數(shù)不能超過(guò)30個(gè)。

          3.    JavaScript中的cookie

           下面來(lái)看一個(gè)設(shè)置cookie的函數(shù),如下所示:

             function setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure) {
           
          var sCookie = sName + “=” +encodeURIComponent(sValue);
           
          if (oExpires) {
                   sCookie 
          +=”; expires=” + oExpires.toGMTString();
          }

          if (sPath) {
                 sCookie 
          += “; path” + sPath;
          }

          if (sDomian) {
                 sCookie 
          += “; domain” + sDomain;
          }

          if (bSecure) {
                 sCookie 
          += “;secure”;
          }

          document.cookie 
          = sCookie;
          }

          setCookie()函數(shù)只有前兩個(gè)參數(shù)是必須的,函數(shù)的調(diào)用方法如下:

          setCookie(“name”, “阿蜜果”);

          setCookie(“book”, “JavaScript高級(jí)程序設(shè)計(jì)”,  new Date(Date.parse(“Jan 1, 2006”)));

          setCookie(“message”, “hello”, new Date(Date.parse(“Jan 1, 2006”)), “/books”, http://www.wrox.com, true );

          下面的函數(shù)是一個(gè)根據(jù)cookie的名稱獲取cookie的方法,代碼如下:

          function getCookie(sName) {
           
          var sRE= "(?:;.)?" + sName + "=([^;]*);?;
           var oRE= new RegExp(sRE);
           if (oRE.test(document.cookie)) {
                 return decodeURIComponent(RegExp[“$1
          ");
          }
           else {
                 
          return null;
          }

          }

           

          調(diào)用該方法可以獲取指定名稱的cookie,調(diào)用舉例如下:

          var sName = getCookie(“name”);

          下面我們?cè)倬帉?xiě)一個(gè)刪除cookie的函數(shù),只需將失效時(shí)間設(shè)為過(guò)去的一個(gè)時(shí)間即可,代碼如下:

          function deleteCookie(sName, sPath, sDomain) {

           setCookie(sName, “”, new Date(0), sPath, sDomain);

          }

           

          4. 服務(wù)器端的cookie

          1JSP

           Jsp提供了非常簡(jiǎn)單的處理cookie的接口,request對(duì)象會(huì)在執(zhí)行JSP時(shí)自動(dòng)初始化,有一個(gè)返回一個(gè)Cookie對(duì)象數(shù)組的方法getCookies()方法。每個(gè)Cookie對(duì)象都具有getName()getPath(), getDomain(),getSecure()getMaxAge()等方法,下面我們還看一個(gè)獲取Cookie的方法:

          public static Cookie getCookie(HttpServletRequest request, String name) {

                 Cookie[] cookies = request.getCookies();

                 if (cookies != null) {

                 for (int i = 0; i<cookies.length; i++) {

                 if (cookies[i].getName().equals(name)) {

                 return cookies[i];

          }

          }

          }

          }

          下面讓我們?cè)賮?lái)看看怎么樣新建一個(gè)cookie

          Cookie nameCookie = new Cookie(“name”, “Amigo”);

          nameCookie.setDomain(“http://www.wrox.com”);

          nameCookie.setPath(“/books”);

          response.addCookie(nameCookie);

          要?jiǎng)h除cookie,可用如下方法:

          Cookie cookieToDelete = getCookie(“name”);

          cookieToDelete.setMaxAge(0);

          response.addCookie(cookieToDelete);

          2ASP.NET

           略。

          3PHP

           略。

           

          二.             隱藏框架

          方法就是創(chuàng)建一個(gè)可用JavaScript與服務(wù)器進(jìn)行通信的0像素高的框架。這種通信方式要求兩部分內(nèi)容:用于處理客戶端通信的JavaScript對(duì)象和在服務(wù)端處理通信的特殊頁(yè)面。Eg.

          <html>

                 <head>

                        <title>隱藏框架的例子</title>

                 </head>

                 <frameset rows=”*, 0”>

                        <frame src=”test1.html” nam=”mainFrame” />

                        <frame src=”hidden.html” nam=”hiddenFrame” />

                 </frameset>

          </html>

          在第一個(gè)框架中,定義了兩個(gè)函數(shù),一個(gè)用于向服務(wù)器發(fā)送請(qǐng)求,另一個(gè)用于處理響應(yīng)。發(fā)送請(qǐng)求的函數(shù)如下:

          function getServerInfo() {

              parent.frames[“hiddenFrame”].location.href = “hiddenFrameCom.html”;

          }

          處理回應(yīng)的函數(shù)handleResponse()的代碼如下:

          function handleResponse(sResponseTextt) {

              alert(“服務(wù)器返回: ” + sResponseTextt);

          }

          處理隱藏請(qǐng)求的頁(yè)面必須輸出一個(gè)普通的HTML頁(yè)面,其中有個(gè)<textarea/>元素,包含返回的元素。使用<textarea/>可以方便的處理多行數(shù)據(jù),這個(gè)頁(yè)面必須在主框架中調(diào)用handleResponse()函數(shù)。實(shí)例代碼如下:

          <html>

              <head>

                     <title>隱藏框架的例子</title>

                     <script type=”text/javascript”>

                     window.onload = function() {

                 parent.frames[0].handleResponse(

                        document.forms[“formResponse”].result.value);

          };

          </script>

                        </head>

                        <body>

                               <form name=”formResponse”>

                                      <textarea name=”result”>傳送回的數(shù)據(jù)</textarea>

                               </form>

                        </body>

                 </html>

           

          三.             HTTP請(qǐng)求

           現(xiàn)在很多瀏覽器都可以直接從JavaScript中初始化HTTP請(qǐng)求并獲取結(jié)果,完全不用隱藏框架和其他取巧的小技巧。

           這個(gè)令人振奮的新功能的核心是,微軟創(chuàng)建的XML HTTP請(qǐng)求的對(duì)象。這個(gè)對(duì)象是與MSXML一起出現(xiàn)的,直到最近它的能力才被完全挖掘。XML HTTP請(qǐng)求實(shí)質(zhì)上是添加了額外的用于發(fā)送和接收XML代碼的功能的普通的HTTP請(qǐng)求。

           要在IE中重新創(chuàng)建XML HTTP請(qǐng)求對(duì)象,還是要使用ActiveXObject,如下所示:

          var oRequest = new ActiveXObject(“Microsoft.XMLHTTP”);

           下面讓我們看一個(gè)創(chuàng)建XML HTTP的方法:

          function createXMLHTTP() {

                 var arrSignatures = [“MSXML2.XMLHTTP.5.0”, “MSXML2.XMLHTTP.4.0”,

          “MSXML2.XMLHTTP.3.0”, “MSXML2.XMLHTTP”,

          “Microsoft.XMLHTTP”];

                 for (var i=0; i< arrSignatures.length; i++) {

                 try {

                        var oRequest = new ActiveXObject(arrSignatures[i]);

                        return oRequest;

          } catch (oError) {

                 //ignore

          }

          }

           

          throw new Error(“你的機(jī)器上沒(méi)有安裝MSXML!”);

          }

          創(chuàng)建好HTTP請(qǐng)求后,可用open()方法來(lái)指定要發(fā)送的請(qǐng)求,該方法的參數(shù)描述如下:

          第一個(gè)參數(shù):值可為“get”或“post”,或其他受服務(wù)器支持的HTTP方法;

          第二個(gè)參數(shù):請(qǐng)求的URL

          第三個(gè)參數(shù):表示請(qǐng)求是否以異步方式發(fā)送的布爾值。

          Eg. oRequest.open(“get”, “example.txt”, false);

          打開(kāi)后,可用send()方法將請(qǐng)求發(fā)送出去,該方法需帶一個(gè)參數(shù),該參數(shù)可為null

          eg. oRequest.send(null);

          下面讓我們來(lái)看一個(gè)比較完整的例子:

          var oRequest = createXMLHTTP();

          oRequest.open(“get”, “example.txt”, false);

          oRequest.send(null);

          alert(“狀態(tài):” + oRequest.status + “(” + oRequest.statusText + “)”);

          alert(“回應(yīng)的文本信息:” + oRequest.responseText);

          該例獲取服務(wù)器端的一個(gè)純文本文件,然后顯示此內(nèi)容。

          如果發(fā)送異步請(qǐng)求,必須使用onreadystatechange事件處理函數(shù),并檢查readyState特性是否等于4(與XML DOM一樣)。讓我們來(lái)看一個(gè)例子:

          var oRequest = createXMLHTTP();

          oRequest.open(“get”, “example.txt”, true);

          oRequest.onreadystatechange = function() {

              if (oRequest.readyState == 4) {

                        alert(“狀態(tài):” + oRequest.status + “(” + oRequest.statusText + “)”);

          alert(“回應(yīng)的文本信息:” + oRequest.responseText);

           

          }

          }

          oRequest.send(null);

          1.       使用HTTP頭部

          XML HTTP請(qǐng)求對(duì)象提供了獲取HTTP頭部和設(shè)置它們的方法:

          l         getAllResponseHeaders():返回包含所有響應(yīng)的HTTP首部信息的字符串;

          l         getResponseHeader():獲取指定的某個(gè)頭部,參數(shù)為獲取的首部的名稱,eg. var sValue = oRequest.getResponseHeader(“Server”);

          l         setResponseHeader():設(shè)置XML HTTP請(qǐng)求的首部信息,eg. oRequest. setResponseHeader(“myheader”, “阿蜜果”).

          2.       實(shí)現(xiàn)的賦值品

          Mozilla第一個(gè)復(fù)制了XML HTTP實(shí)現(xiàn),創(chuàng)建了名為XMLHTTPRequestJavaScript,行為完全與微軟的版本相同,Opera(7.6)Safari1.2)也復(fù)制了Mozilla的實(shí)現(xiàn),創(chuàng)建了自己的XMLHTTPRequest對(duì)象。

          3.       進(jìn)行GET請(qǐng)求

          Web上最常見(jiàn)的請(qǐng)求類型就是GET請(qǐng)求,下面讓我們來(lái)看一個(gè)GET請(qǐng)求的例子,代碼如下所示:

          首先為了添加參數(shù)的方便性,讓我們?cè)黾右粋€(gè)添加參數(shù)的方法,然后為請(qǐng)求構(gòu)建一個(gè)URL,代碼如下所示:

          function addURLParam(url, sParamName, sParamValue) {

              url += (url.indexOf(“?”) == -1 ? “?” : “&”);

              url += encodeURIComponent(sParamName) + “=” + encodeURIComponent(sParamValue);

              return url;

          }

          var url =  “http://www.aygfsteel.com/amigoxie”;

          url = addURLParam(url, “gender”, “”);

          url = addURLParam(url, “age”, “25”);

          oRequest.open(“get”, url, false);

          4.       進(jìn)行POST請(qǐng)求

          POST請(qǐng)求用于在表單中輸入數(shù)據(jù)后的提交過(guò)程,因?yàn)?/span>POST可以比GET方式發(fā)送更多數(shù)據(jù)(最多2GB)。讓我們來(lái)可看一個(gè)例子:

          function addPostParam(sParams, sParamName, sParamValue) {

              if (sParams.length > 0) {

                 sParams += “&”;

          }

              return sParams + encodeURIComponent(sParamName) + “=” + encodeURIComponent(sParamValue);

          }

           

          Var sParams = “”;

          sParams = addPostParam(sParams, “gender”, “”);

          sParams = addPostParam(sParams, “age”, “25”);

          oRequest.open(“open”, “test.jsp”, false);

          oRequest.send(sParams);

           

          四.             LiveConnect請(qǐng)求

           LiveConnectNetscape Navigator引入,一般可以讓JavaScriptJava類實(shí)現(xiàn)交互的能力。用戶必須安裝JRE,并且還需在瀏覽器中啟用Java

          1.       進(jìn)行GET請(qǐng)求

          使用Live Connect時(shí),必須提供類的完整名稱,才能初始化一個(gè)Java對(duì)象。創(chuàng)建URL后,就可以打開(kāi)一個(gè)輸入流并使用讀取器來(lái)讀取數(shù)據(jù)。最好的方法是創(chuàng)建一個(gè)InputStreamReader,然后再基于它創(chuàng)建一個(gè)BufferReader,實(shí)例代碼如下:

          function httpGet(url) {

              var ourl = new java.net.URL(url);

          var oStream = ourl.openStream();

          var oReader = new java.io.BufferedReader(new java.io.InputStreamReader(oStream));

          var oResponseText = “”;

          var sLine = oReader.readLine();

          while (sLine != null) {

                 oResponseText += sLine + “\n”;

                 sLine = oReader.readLine();

          }

          oReader.close();

          return oResponseText;

          }

          注意:與XML HTTP請(qǐng)求對(duì)象不通,LiveConnect要求輸入完整的請(qǐng)求的URL,從http://開(kāi)始,因?yàn)椋@個(gè)Java對(duì)象沒(méi)有任何解釋相對(duì)URL的上下文。

          2.       進(jìn)行POST請(qǐng)求

          因?yàn)?/span>POST請(qǐng)求可看作是雙向的,所以必須使用setDoInput()setDoOutput()方法將連接設(shè)成接受輸入和輸出。另外,連接不應(yīng)該使用任何緩存數(shù)據(jù),所以要調(diào)用setUseCaches(false)。與XML HTTP請(qǐng)求對(duì)象一樣,還必須用setRequestProperty()方法將“Content-Type”設(shè)置為相應(yīng)的值。代碼如下:

          function httpPost(url, sParams) {

              var ourl = new java.net.URL(url);

              var oConnection = ourl.openConnection();

           

              oConnection.setDoInput(true);

              oConnection.setDoOutput(true);

              oConnection.setUseCaches(false);

              oConnection.setRequestProperty(“Content-Type”,

          “application/x-www-form-urlencoded”);

           

                 var output = new java.io.DataOutputStream(oConnection.getOutputStream());

                 output.writeBytes(sParams);

                 output.flush();

                 output.close();

           

                 var sLine = “”, sResponseText = “”;

                 var input = new java.io.DataInputStream(oConnection.getInputStream());

                 sLine = input.readLine();

                 while (sLine != null) {

                 sResponseText += sLine + “\n”;

                        sLine = input.readLine();

          }

           

          input.close();

          return oResponseText;

          }

           

          五.             智能HTTP請(qǐng)求

           對(duì)于兩種完全不同的HTTP請(qǐng)求方法,有一系列通用的函數(shù)會(huì)對(duì)開(kāi)發(fā)很有幫助。

          1.       get()方法
           
          該方法用于對(duì)指定的URL進(jìn)行一個(gè)GET請(qǐng)求。該方法有兩個(gè)參數(shù):發(fā)送請(qǐng)求的URL和一個(gè)回調(diào)函數(shù)。回調(diào)函數(shù)在很多編程語(yǔ)言中是用于在請(qǐng)求結(jié)束時(shí)通知開(kāi)發(fā)者的。整合后的通用的get()方法代碼如下:

          var bXmlHttpSupport = (typeof XMLHttpRequest == “object” || window.ActiveXObject);

          Http.get = function (url, fnCallback) {

                 if (bXmlHttpSupport) {

                 var oRequest = new XMLHttpRequest();

                 oRequest.open(“get”, url, true);

                 oRequest.onreadystatechange = function() {

                 if (oRequest.readyState == 4) {

                 fnCallback(oRequest.responseText);

          }

          }

          oRequest.send(null);

          } else if (navigator.javaEnabled() && typeof java != “undefined”

          && type java.net != “undefined”) {

          setTimeout(function() {

                 fnCallback(httpGet(url));

          }, 10);

          } else {

                 alert(“你的瀏覽器不支持HTTP請(qǐng)求!”);

          }

          }

          2.       post()方法

          除了需要三個(gè)參數(shù)(URL、參數(shù)字符串和回調(diào)函數(shù))外,post()方法類似于get()方法。代碼如下:

          var bXmlHttpSupport = (typeof XMLHttpRequest == “object” || window.ActiveXObject);

          Http.post = function(url, sParams, fnCallback) {

                  if (bXmlHttpSupport) {

                 var oRequest = new XMLHttpRequest();

                 oRequest.open(“post”, url, true);

                 oRequest.setRequestHeader(“Content-Type”,

          “application/x-www-form-urlencoded”);

                               oRequest.onreadysatechange = function() {

                 if (oRequest.readyState == 4) {

                        fnCallback(oRequest.responseText);

          }

          }

          } else if ((navigator.javaEnabled() && typeof java != “undefined”

          && type java.net != “undefined”) {

                 setTimeout(function() {

                 fnCallback(httpPost(url, sParams));

          }, 10);

          } else {

                 alert(“你的瀏覽器不支持HTTP請(qǐng)求!”);

          }

          }

          注意:使用這個(gè)方法必須提供完整的URL.

          posted on 2007-08-15 08:43 阿蜜果 閱讀(4862) 評(píng)論(3)  編輯  收藏 所屬分類: Javascript


          FeedBack:
          # re: JavaScript學(xué)習(xí)筆記——客戶端與服務(wù)器端的通信
          2007-08-15 09:37 | dudu
          學(xué)習(xí)筆記不適合發(fā)表在首頁(yè),javascript方面的文章建議放在其他技術(shù)區(qū)。  回復(fù)  更多評(píng)論
            
          # re: JavaScript學(xué)習(xí)筆記——客戶端與服務(wù)器端的通信[未登錄](méi)
          2007-08-15 09:57 | 阿蜜果
          @dudu
          知道了,多謝提醒  回復(fù)  更多評(píng)論
            
          # re: JavaScript學(xué)習(xí)筆記——客戶端與服務(wù)器端的通信
          2007-08-20 10:01 | cresposhi
          dudu有偏見(jiàn)啊,javascript已經(jīng)成為J2EE程序員必須熟練掌握的語(yǔ)言之一,重要性與java已經(jīng)無(wú)異。
          希望dudu老大能夠與時(shí)俱進(jìn),共建和諧啊!  回復(fù)  更多評(píng)論
            
          <2007年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

                生活將我們磨圓,是為了讓我們滾得更遠(yuǎn)——“圓”來(lái)如此。
                我的作品:
                玩轉(zhuǎn)Axure RP  (2015年12月出版)
                

                Power Designer系統(tǒng)分析與建模實(shí)戰(zhàn)  (2015年7月出版)
                
               Struts2+Hibernate3+Spring2   (2010年5月出版)
               

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊(cè)

          關(guān)注blog

          積分與排名

          • 積分 - 2296332
          • 排名 - 3

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 达尔| 台山市| 宝山区| 商洛市| 济南市| 西乌珠穆沁旗| 泗洪县| 安多县| 墨玉县| 富民县| 射阳县| 石阡县| 剑川县| 沙雅县| 乌海市| 诏安县| 巴青县| 小金县| 萝北县| 承德市| 进贤县| 建德市| 奉贤区| 桦川县| 沁水县| 巴塘县| 宜阳县| 如皋市| 囊谦县| 会泽县| 鄂伦春自治旗| 和平区| 沐川县| 深泽县| 博湖县| 卓尼县| 泰顺县| 陆川县| 庄浪县| 余干县| 菏泽市|