滿店香的家

          學(xué)習(xí)+實(shí)踐=進(jìn)步

          第三部分 DWR的技術(shù)基石-無刷新訪問服務(wù)器

              從2005年開始,ajax在全球漸漸掀起了一股潮流,它使瀏覽器可以為用戶提供更為自然的瀏覽體驗(yàn),全球幾百個(gè)ajax項(xiàng)目中,dwr就是其中一項(xiàng)。
               ajax采用的技術(shù)基石其實(shí)早就有了,就是“無刷新訪問服務(wù)器”技術(shù),所以有人說ajax其實(shí)就是新瓶裝老酒,一點(diǎn)沒錯(cuò),就是新瓶裝老酒,在工程師們將“無刷新訪問服務(wù)器”技術(shù)封裝成各種套件工具時(shí),確實(shí)給我們帶來了驚喜,也帶來了新的響亮的名字ajax(Asynchronous JavaScript and XML)。
          第一步,我們要回顧“無刷新訪問服務(wù)器”技術(shù)。
          第二步,在源碼中找到dwr中“無刷新訪問服務(wù)器”技術(shù)的原始代碼。
          第三步,我們再簡單的總結(jié)總結(jié)。
                1)“無刷新訪問服務(wù)器”技術(shù)

          var xmlhttp=null;
          function PostOrder(xmldoc)
          {
            
          var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.5.0");
            xmlhttp.Open(
          "POST""http://myserver/orders/processorder.asp";, false); //設(shè)置XMLHTTP對象,這個(gè)對象可以執(zhí)行向預(yù)定目標(biāo)地址以Post方式發(fā)送數(shù)據(jù)包。
          //
          http://myserver/orders/processorder.asp服務(wù)器端專門用來接收數(shù)據(jù)的地址
            xmlhttp.onreadystatechange= HandleStateChange;//設(shè)置客戶端響應(yīng)狀態(tài),發(fā)送數(shù)據(jù)后,服務(wù)器會(huì)響應(yīng)
            xmlhttp.Send(xmldoc);//發(fā)送數(shù)據(jù),xmldoc是xml結(jié)構(gòu)化的數(shù)據(jù)
            myButton.disabled = true;
          }

          function HandleStateChange()
          {
            
          if (xmlhttp.readyState == 4)//當(dāng)收到正確響應(yīng)時(shí)狀態(tài)變成4,否則一直等待
            {
              myButton.disabled 
          = false;
              alert(
          "Result = " + xmlhttp.responseXML.xml);//返回的數(shù)據(jù)
            }

          }


          var xmlDoc=new ActiveXObject("MSXML2.DOMDocument");
          flag
          =xmlDoc.loadXML("");

            newNode 
          =xmlDoc.createElement("編碼")
            MarkNode
          =xmlDoc.documentElement.appendChild(newNode);
            newNode 
          =xmlDoc.createElement("StartMark")
            newNode.text
          =StartMark;
            MarkNode.appendChild(newNode)
            newNode 
          =xmlDoc.createElement("EndMark")
            newNode.text
          =EndMark;
            MarkNode.appendChild(newNode)
            
            newNode 
          =xmlDoc.createElement("日期")
            DateNode
          =xmlDoc.documentElement.appendChild(newNode);
            newNode 
          =xmlDoc.createElement("StartDate");
            newNode.text
          =StartDate;
            DateNode.appendChild(newNode)
            newNode 
          =xmlDoc.createElement("EndDate")
            newNode.text
          =EndDate;
            DateNode.appendChild(newNode);
              上面的代碼很好理解吧。好了,這里要給出補(bǔ)充了,實(shí)際上ActiveXObject是IE支持的類型,假如瀏覽器不支持這個(gè)呢
          摘錄了一段比較細(xì)的解釋:
          1:先建立XMLHttpRequest,建立成功以后要在它的后面緊跟著建立一個(gè)xhr.overrideMimeType("text/xml")對于該句的解釋在天極網(wǎng)找到了這么一段話“如果服務(wù)器的響應(yīng)沒有XML mime-type header,某些Mozilla瀏覽器可能無法正常工作。為了解決這個(gè)問題,如果服務(wù)器響應(yīng)的header不是text/xml,可以調(diào)用其它方法修改該header”。
           
          if(window.XMLHttpRequest){
             xhr 
          = new XMLHttpRequest();
             
          if(xhr.overrideMimeType)
                
          { xhr.overrideMimeType("text/xml") ;}
          }

          2:如果XMLHttpRequest建立不成功就要建立針對IE的ActiveXObject.不同的IE版本有不同ActiveXObject,但是我們現(xiàn)在只要建立兩個(gè)就可以了,163是這樣做的于是我也就理解為這樣就可以兼容所有的IE了,具體沒測試過.
            
          try{
               xhr 
          = new ActiveXObject("Msxml.XMLHTTP");
              }
          catch(e){
              
          try{
                xhr 
          = new ActiveXObject("Microsoft.XMLHTTP");
                 }

              
          catch(e){}
            }
          兩個(gè)try嵌套把兩種情況都寫出來了.


               到現(xiàn)在為止,算是回顧了無狀態(tài)刷新技術(shù)。

               2)dwr中“無刷新訪問服務(wù)器”技術(shù)的原始代碼
               在dwr.jar包里,可以找到文件\org\directwebremoting\engine.js,有如下的代碼片段,在這段代碼中,我們能夠找到“無刷新訪問服務(wù)器”技術(shù)的原始代碼,關(guān)注這段代碼中的“看這里”,代碼相對于上面,膨脹了很多呢,主要是處理意外、特殊情況的代碼,沒必要仔細(xì)研究。

              /**
               * Remoting through XHR
               
          */

              xhr:
          {
                
          /**
                 * The default HTTP method to use
                 
          */

                httpMethod:
          "POST",

                
          /**
                 * The ActiveX objects to use when we want to do an XMLHttpRequest call.
                 * TODO: We arrived at this by trial and error. Other toolkits use
                 * different strings, maybe there is an officially correct version?
                 
          */

                XMLHTTP:[
          "Msxml2.XMLHTTP.6.0""Msxml2.XMLHTTP.5.0""Msxml2.XMLHTTP.4.0""MSXML2.XMLHTTP.3.0""MSXML2.XMLHTTP""Microsoft.XMLHTTP"],

                
          /**
                 * Setup a batch for transfer through XHR
                 * @param {Object} batch The batch to alter for XHR transmit
                 
          */

                send:
          function(batch) {
                  
          if (batch.isPoll) {
                    batch.map.partialResponse 
          = dwr.engine._partialResponseYes;
                  }


                  
          // Do proxies or IE force us to use early closing mode?
                  if (batch.isPoll && dwr.engine._pollWithXhr == "true"{
                    batch.map.partialResponse 
          = dwr.engine._partialResponseNo;
                  }

                  
          if (batch.isPoll && dwr.engine.isIE) {
                    batch.map.partialResponse 
          = dwr.engine._partialResponseNo;
                  }

                  
          //看這里
                  if (window.XMLHttpRequest) {
                    batch.req 
          = new XMLHttpRequest();
                  }

                  
          else if (window.ActiveXObject) {
                    batch.req 
          = dwr.engine.util.newActiveXObject(dwr.engine.transport.xhr.XMLHTTP);
                  }

                  
          //看這里

                  
          // Proceed using XMLHttpRequest
                  if (batch.async) {
                    batch.req.onreadystatechange 
          = function() {
                      
          if (typeof dwr != 'undefined') {
                        dwr.engine.transport.xhr.stateChange(batch);
                      }

                    }
          ;
                  }


                  
          // If we're polling, record this for monitoring
                  if (batch.isPoll) {
                    dwr.engine._pollReq 
          = batch.req;
                    
          // In IE XHR is an ActiveX control so you can't augment it like this
                    if (!document.all) batch.req.batch = batch;
                  }


                  httpMethod 
          = dwr.engine.transport.xhr.httpMethod;

                  
          // Workaround for Safari 1.x POST bug
                  var indexSafari = navigator.userAgent.indexOf("Safari/");
                  
          if (indexSafari >= 0{
                    
          var version = navigator.userAgent.substring(indexSafari + 7);
                    
          if (parseInt(version, 10< 400{
                      
          if (dwr.engine._allowGetForSafariButMakeForgeryEasier == "true"{
                        httpMethod 
          = "GET";
                      }

                      
          else {
                        dwr.engine._handleWarning(batch, 
          {
                          name: 
          "dwr.engine.oldSafari",
                          message: 
          "Safari GET support disabled. See getahead.org/dwr/server/servlet and allowGetForSafariButMakeForgeryEasier."
                        }
          );
                      }

                    }

                  }


                  batch.mode 
          = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
                  
          var request = dwr.engine.batch.constructRequest(batch, httpMethod);

                  
          try {
                    batch.req.open(httpMethod, request.url, batch.async);
          //看這里,發(fā)送設(shè)置
                    try {
                      
          for (var prop in batch.headers) {
                        
          var value = batch.headers[prop];
                        
          if (typeof value == "string"{
                          batch.req.setRequestHeader(prop, value);
                        }

                      }

                      
          if (!batch.headers["Content-Type"]) {
                        batch.req.setRequestHeader(
          "Content-Type""text/plain");
                      }

                    }

                    
          catch (ex) {
                      dwr.engine._handleWarning(batch, ex);
                    }

                    batch.req.send(request.body);
          //看這里,執(zhí)行發(fā)送
                    if (!batch.async) {
                      dwr.engine.transport.xhr.stateChange(batch);
                    }

                  }

                  
          catch (ex) {
                    dwr.engine._handleError(batch, ex);
                  }


                  
          if (batch.isPoll && batch.map.partialResponse == dwr.engine._partialResponseYes) {
                    dwr.engine.transport.xhr.checkCometPoll();
                  }


                  
          // This is only of any use in sync mode to return the reply data
                  return batch.reply;
                }
          ,

              3)在batch.req.send(request.body)代碼行上添加alert("see me:"+request.body);可以看到執(zhí)行發(fā)送時(shí),到底發(fā)送了什么。
               1,在我進(jìn)入dwr工程的首頁時(shí)。alert彈出的內(nèi)容如下:

          see me:callCount=1
          windowName
          =DWR-4B6B.06
          c0
          -scriptName=_System
          c0
          -methodName=pageLoaded
          c0
          -id=0
          batchId
          =0
          page
          =/dwr/
          httpSessionId
          -
          scriptSessionId
          =
              2,在我們進(jìn)入樣例Dynamically Text中,點(diǎn)擊發(fā)送時(shí),alert彈出內(nèi)容
          see me:callCount=1
          windowName
          =DWR-4B6B.2D06
          c0
          -scriptName=Demo
          c0
          -methodName=sayHello
          c0
          -id=0
          c0
          -param0=string:Joe
          batchId
          =1
          page
          =/dwr/simpletext/index.html
          httpSessionId
          =
          scriptSessionId
          =A822701A

              3,當(dāng)我進(jìn)入樣例Edit Table時(shí),刪除表中一行時(shí),alert彈出內(nèi)容

          see me:callCount=2
          windowName
          =DWR-4B6B.D06
          c0
          -scriptName=People
          c0
          -methodName=deletePerson
          c0
          -id=0
          c0
          -e1=number:18
          c0
          -param0=Object_Object:{id:reference:c0-e1}
          c1
          -scriptName=People
          c1
          -methodName=getAllpeople
          c1
          -id=1
          batchId
          =2
          page
          =/dwr/people/index.html
          httpSessionId
          =
          scriptSessionId
          =2557C..42A1

             看看上面這些,比較比較不同處,現(xiàn)在可能還不好理解,當(dāng)我們在后面講解dwr原理時(shí),回過頭來看會(huì)更能理解。
             我們先提前解釋一下:
             callCount=1                         表示執(zhí)行了多少個(gè)方法
             c0-scriptName =Demo         調(diào)用了那個(gè)java類   c后面的序號是方法的序號,如果有兩個(gè)方法,那么就有c0,c1,見第三個(gè)例子
             c0-methodName=sayHello    調(diào)用了類中的哪個(gè)方法
             c0-id =0                               方法序號        
             c0-param1=String: Joe          傳遞的值,這個(gè)值對應(yīng)于java方法的參數(shù)
             page=/dwr/..                         路徑

             總結(jié):
              dwr通過無狀態(tài)刷新技術(shù),向服務(wù)器端發(fā)送數(shù)據(jù)包,服務(wù)器端響應(yīng),客戶端收到返回?cái)?shù)據(jù)后,作出變化。
              下面這一段話是更詳細(xì)的技術(shù)細(xì)節(jié)
               【
                   以樣例Dynamically Text為例
                   在瀏覽器加載http://localhost:5050/dwr/simpletext/index.html時(shí),
                   瀏覽器遇到下面這句話
                   <script type='text/javascript' src='../dwr/interface/Demo.js'> </script>
                   就執(zhí)行dwrServlet.java(web.xml有dwr相關(guān)配置),向服務(wù)器調(diào)用發(fā)送類似于樣例1的內(nèi)容,不執(zhí)行任何操作。
                   當(dāng)我們真正點(diǎn)擊發(fā)送按鈕時(shí),向服務(wù)器發(fā)送樣例2的數(shù)據(jù),告訴服務(wù)器,我會(huì)調(diào)用哪個(gè)類的哪個(gè)方法,并且傳什么樣的參數(shù),參數(shù)內(nèi)容是什么。
                   不用說,服務(wù)器端肯定是接收相應(yīng)的數(shù)據(jù),激發(fā)相應(yīng)的類相應(yīng)的方法
                   對于參數(shù),涉及到字符串?dāng)?shù)據(jù)比如String:Joe,轉(zhuǎn)換為java對象,有專門的轉(zhuǎn)換類處理,后綴為convert的類
                】
              

              

          posted on 2008-04-05 01:31 滿店香 閱讀(1436) 評論(0)  編輯  收藏 所屬分類: dwr源碼分析

          主站蜘蛛池模板: 泉州市| 安化县| 金坛市| 伽师县| 铜川市| 浙江省| 衡阳县| 彰化县| 安顺市| 工布江达县| 榕江县| 巴林左旗| 扎赉特旗| 云和县| 通化县| 上犹县| 凤阳县| 磐安县| 襄汾县| 罗城| 马边| 德庆县| 定南县| 红桥区| 开远市| 嘉定区| 东光县| 永昌县| 汨罗市| 喀什市| 梓潼县| 稷山县| 梁平县| 山阳县| 阳曲县| 松原市| 上林县| 枣阳市| 澄江县| 白银市| 栖霞市|