第三部分 DWR的技术基石-无刷新访问服务器

  从2005年开始,ajax在全球渐渐掀起了一股潮流,它使浏览器可以为用户提供更为自然的浏览体验,全球几百个ajax项目中,dwr就是其中一项。
     ajax采用的技术基石其实早就有了,就是“无刷新访问服务器”技术,所以有人说ajax其实就是新瓶装老酒,一点没错,就是新瓶装老酒,在工程师们将“无刷新访问服务器”技术封装成各种套件工具时,确实给我们带来了惊喜,也带来了新的响亮的名字ajax(Asynchronous JavaScript and XML)。
第一步,我们要回顾“无刷新访问服务器”技术。
第二步,在源码中找到dwr中“无刷新访问服务器”技术的原始代码。
第三步,我们再简单的总结总结。
      1)“无刷新访问服务器”技术

var  xmlhttp = null ;
function  PostOrder(xmldoc)
{
  
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.5.0");
  xmlhttp.Open(
"POST""http://myserver/orders/processorder.asp";, false); //设置XMLHTTP对象,这个对象可以执行向预定目标地址以Post方式发送数据包。
//
http://myserver/orders/processorder.asp服务器端专门用来接收数据的地址
  xmlhttp.onreadystatechange= HandleStateChange;//设置客户端响应状态,发送数据后,服务器会响应
  xmlhttp.Send(xmldoc);//发送数据,xmldoc是xml结构化的数据
  myButton.disabled = true;
}

function  HandleStateChange()
{
  
if (xmlhttp.readyState == 4)//当收到正确响应时状态变成4,否则一直等待
  {
    myButton.disabled 
= false;
    alert(
"Result = " + xmlhttp.responseXML.xml);//返回的数据
  }

}


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

    上面的代码很好理解吧。好了,这里要给出补充了,实际上ActiveXObject是IE支持的类型,假如浏览器不支持这个呢
摘录了一段比较细的解释:

1 :先建立XMLHttpRequest,建立成功以后要在它的后面紧跟着建立一个xhr.overrideMimeType( " text/xml " )对于该句的解释在天极网找到了这么一段话“如果服务器的响应没有XML mime - type header,某些Mozilla浏览器可能无法正常工作。为了解决这个问题,如果服务器响应的header不是text / xml,可以调用其它方法修改该header”。
 
if (window.XMLHttpRequest) {
   xhr 
= new XMLHttpRequest();
   
if(xhr.overrideMimeType)
      
{ xhr.overrideMimeType("text/xml") ;}
}

2 :如果XMLHttpRequest建立不成功就要建立针对IE的ActiveXObject.不同的IE版本有不同ActiveXObject,但是我们现在只要建立两个就可以了,163是这样做的于是我也就理解为这样就可以兼容所有的IE了,具体没测试过.
  
try {
     xhr 
= new ActiveXObject("Msxml.XMLHTTP");
    }
catch (e) {
    
try{
      xhr 
= new ActiveXObject("Microsoft.XMLHTTP");
       }

    
catch(e){}
  }
两个try嵌套把两种情况都写出来了.


     到现在为止,算是回顾了无状态刷新技术。

     2)dwr中“无刷新访问服务器”技术的原始代码
     在dwr.jar包里,可以找到文件/org/directwebremoting/engine.js,有如下的代码片段,在这段代码中,我 们能够找到“无刷新访问服务器”技术的原始代码,关注这段代码中的“看这里”,代码相对于上面,膨胀了很多呢,主要是处理意外、特殊情况的代码,没必要仔 细研究。

     /**
     * 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);
//看这里,发送设置
          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);
//看这里,执行发送
          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);可以看到执行发送时,到底发送了什么。
     1,在我进入dwr工程的首页时。alert弹出的内容如下:

see me:callCount = 1
windowName
= DWR - 4B6B. 06
c0
- scriptName = _System
c0
- methodName = pageLoaded
c0
- id = 0
batchId
= 0
page
=/ dwr /
httpSessionId
-
scriptSessionId
=

    2,在我们进入样例Dynamically Text中,点击发送时,alert弹出内容

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,当我进入样例Edit Table时,删除表中一行时,alert弹出内容

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

   看看上面这些,比较比较不同处,现在可能还不好理解,当我们在后面讲解dwr原理时,回过头来看会更能理解。
   我们先提前解释一下:
   callCount=1                         表示执行了多少个方法
   c0-scriptName =Demo         调用了那个java类   c后面的序号是方法的序号,如果有两个方法,那么就有c0,c1,见第三个例子
   c0-methodName=sayHello    调用了类中的哪个方法
   c0-id =0                               方法序号        
   c0-param1=String: Joe          传递的值,这个值对应于java方法的参数
   page=/dwr/..                         路径

   总结:
    dwr通过无状态刷新技术,向服务器端发送数据包,服务器端响应,客户端收到返回数据后,作出变化。
    下面这一段话是更详细的技术细节
     【
         以样例Dynamically Text为例
         在浏览器加载http://localhost:5050/dwr/simpletext/index.html时,
         浏览器遇到下面这句话
         <script type='text/javascript' src='../dwr/interface/Demo.js'> </script>
         就执行dwrServlet.java(web.xml有dwr相关配置),向服务器调用发送类似于样例1的内容,不执行任何操作。
         当我们真正点击发送按钮时,向服务器发送样例2的数据,告诉服务器,我会调用哪个类的哪个方法,并且传什么样的参数,参数内容是什么。
         不用说,服务器端肯定是接收相应的数据,激发相应的类相应的方法
         对于参数,涉及到字符串数据比如String:Joe,转换为java对象,有专门的转换类处理,后缀为convert的类
      】

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值