`

DWR整体流程分析(二)(转)

    博客分类:
  • dwr
 
阅读更多

看一下sessionCookieName:

 

/** The session cookie name */  
dwr.engine._sessionCookieName = "${sessionCookieName}"; // JSESSION

 

 ID 

The session cookie name它也是服务器端返回给客户端的,所以说服务器端采用什么方式获得了这个sessionCookieName的形式之后,我们的dwr.engine._getJSessionId才能根据它的内容它的形式来返回我们想要的cookie,这个实现方式就是dwr所依赖的实现方式。如果dwr实现了这个cookieName是别的名字,那我们也需要dwr给返回别的名字。dwr.engine._sessionCookieName 这个名字是因框架而定。所以它会采用这样一种写法。 
我们看看打印 

 

function show(){   
alert("sessionCookieName:" + dwr.engine._sessionCookieName);   
}  

 

 打印出sessionCookieName:JSESSIONID 

那么我们现在取得的JSESSIONID就是JSESSIONID=我们所要的字符串,我们验证一下,用下面的代码:

 

var cookies = document.cookie.split(';');   
alert(cookies );  

 

 打印出JSESSIONID=FCB69D86F4E1AC9CF3900A6816。它和origScriptSessionId是不一样的。我们来看看httpSessionId(JSESSIONID),它应该是对一个客户的所有请求来讲的。会话,对多个请求只要是同一个客户都可以,因此对于同一个客户它的httpSessionId是不会变的。我们来看对同一个客户第一次请求JSESSIONID=FCB69D86F4E1AC9CF3900A6816,刷新后第二次请求JSESSIONID=FCB69D86F4E1AC9CF3900A6816,它们俩次显示的JSESSIONID是相同的。因为它们都是相当于同一会话来讲的。这个内容也就是存储在客户端,客户端发送数据的时候也要把它们发送出去,发送出去到服务器端后,服务器端判断这个SESSIONID存不存在。如果存在的话,就会根据它去取出我们所要的session,然后把当前客户这些状态取出来显示出来。 

我们看一下原始的脚本ScriptSessionId,我们知道它的产生是服务器每一次进行加载页面,页面中包含了engine.js这个资源的时候,我们会把原始的ScriptSessionId赋值,所以我们每一次的请求都会产生一个不同的ScriptSessionId。所以脚本的原始的ScriptSessionId,针对每一次的不同请求,它都会产生不同的原始的ScriptSessionId。 
(四)execute方法 
下面我们看一下脚本文件的生成: 
Demo.js: 

 

//Provide a default path to dwr.engine   
if(dwr == null) var dwr = {};   
if(dwr.engine == null) dwr.engine = {};   
if(DWREngine == null) var DWREngine = dwr.engine;   
  
if(Demo == null) var Demo = {};   
Demo._path = '/Demo1/dwr';   
Demo.sayHello = function(p0,callback){   
    dwr.engine._execute(Demo._path,'Demo','sayHello',p0,callback);   
}  

 

 这是服务器端为我们产生的脚本文件,正因为有了这个脚本文件,客户端才可以通过Demo.sayHello来访问到服务器组件。到底是怎么访问的?大家知道,dwr是基于ajax产生的,所以它必然会用到ajax的xmlHttpRequest对象,被dwr封装了,包括servlet在ajax中也需要我们来写,但是在dwr中也封装来了,只要在web.xml配置org.directwebremoting.servlet.DwrServlet就可以完成我们的处理了。这也是dwr优于ajax的一点,框架的集成度是比较高的。 

看一下Demo.sayHello,它是通过dwr.xml这个部署配置文件来动态产生的, dwr.engine._execute(Demo._path,'Demo','sayHello',p0,callback);这些东西是服务器发我们的,这是dwr的一个内部实现机制。看一下调用Demo.sayHello方法的时候,具体的操作是什么?它首先去调用函数function(p0,callback),说白了,客户端直接调用web服务器的组件呢,实际说到最终的实质也就是服务器端为我们产生一个js脚本文件,产生的这个文件是根据我们的dwr.xml部署描述文件动态生成的,生成之后呢,我们客户端就调用生成的这个文件当中的信息,然后通过这个信息再去调用engine.js文件当中的execute方法,然后把必要的参数传递进去之后,在dwr.engine._execute(Demo._path,'Demo','sayHello',p0,callback);里面完成对象的创建,包括最后的发送,最后的相应等等。所以这个引擎的脚本文件是很重要的。下面分析一下引擎脚本文件中的 
dwr.engine._execute方法: 

 

dwr.engine._execute = function(path, scriptName, methodName, vararg_params) 

 

 引擎文件的执行方法,需要4个参数,注意一点,看源码的时候, javascript定义一个函数的时候,后面的参数并不是我们在dwr.engine._execute(Demo._path,'Demo','sayHello',p0,callback);里面指定的,因为这是5个参数,但前面引擎文件的执行方法定义时却只有4个参数。这个和强类型语言有所区别,强类型语言对于函数重载方面,它参数不同,它会去调用不同的方法。但是这里如果仅仅有一个函数的话,这个函数的参数不同,它也会去调用。所以不能从参数的数量上来确定调用哪一个函数。vararg_params相当于是一个数组,相当于有很多的参数在里面,这一点一定要注意。所以客户端在调用了Demo.sayHello方法之后,会执行引擎脚本的execute方法,然后会传递几个参数Demo._path,'Demo','sayHello',p0,callback。Demo._path是在服务器端动态的生成的,它也就是指定我们请求的路径是什么。请求都是通过servlet来处理的,请求路径应该就是servlet所需要的路径。Demo指的是dwr.xml文件当中,为我们指定的javascript的属性所指定的在客户端调用的对象的方法的对象的名称,sayHello就是指定我所调用的是哪一个方法,p0就是指定调用的参数是什么(就是本例的name),callback就是回调方法。这就是我们在客户端在书写格式上要采用Demo.sayHello(text,callBack),前面text指的是参数,后面指定的是回调函数callBack。这也是和实现机制有关的,否则我们这么写为什么会去调用它,我们不得而知,但是当你看到了这个生成的引擎文件的时候,我就知道,实际我调用sayHello方法之后,传递的两个参数function(p0,callback),p0是我们传递的参数,callback是回调方法,然后吧这些信息是通过引擎文件的execute方法去执行的。但是传递这个方法的时候,会传递另外一些附加的信息。而且回调函数传过去,传过去之后在引擎中,会对数据进行分析,分析之后回传的时候会去调用callback,然后就会调用我们在index.jsp里面写的callBack(data)方法显示出数据。这就是整体流程。 

下面分析引擎文件的执行方法,看源码: 

 

dwr.engine._execute = function(path, scriptName, methodName, vararg_params){   
var singleShot = false;   
  if (dwr.engine._batch == null) {   
    dwr.engine.beginBatch();   
    singleShot = true;   
  }   
  var batch = dwr.engine._batch;   
  // To make them easy to manipulate we copy the arguments into an args array   
  var args = [];   
  for (var i = 0; i < arguments.length - 3; i++) {   
    args[i] = arguments[i + 3];   
  }   
  // All the paths MUST be to the same servlet   
  if (batch.path == null) {   
    batch.path = path;   
  }   
  else {   
    if (batch.path != path) {   
      dwr.engine._handleError(batch, { name:"dwr.engine.multipleServlets", message:"Can't batch requests to multiple DWR Servlets." });   
      return;   
    }   
  }   
  // From the other params, work out which is the function (or object with   
  // call meta-data) and which is the call parameters   
  var callData;   
  var lastArg = args[args.length - 1];   
  if (typeof lastArg == "function" || lastArg == null) callData = { callback:args.pop() };   
  else callData = args.pop();   
  
  // Merge from the callData into the batch   
  dwr.engine._mergeBatch(batch, callData);   
  batch.handlers[batch.map.callCount] = {   
    exceptionHandler:callData.exceptionHandler,   
    callback:callData.callback   
  };   
  
  // Copy to the map the things that need serializing   
  var prefix = "c" + batch.map.callCount + "-";   
  batch.map[prefix + "scriptName"] = scriptName;   
  batch.map[prefix + "methodName"] = methodName;   
  batch.map[prefix + "id"] = batch.map.callCount;   
  for (i = 0; i < args.length; i++) {   
    dwr.engine._serializeAll(batch, [], args[i], prefix + "param" + i);   
  }   
  
  // Now we have finished remembering the call, we incr the call count   
  batch.map.callCount++;   
  if (singleShot) dwr.engine.endBatch();   
  
};  

 

 path是请求的路径,scriptName是客户端所用的java对象的名称methodName是调用的方法名 vararg_params是方法的参数,这里面的参数是包括了客户端发送给服务器端需要的java方法的参数名称,还有一个就是回调函数。 

首先看看dwr.engine.beginBatch();开始一个批处理,目的是因为dwr框架在开发的时候遵循的一种方式就是说,如果多次调用java的web组件的话,我需要放在一个批处理当中来处理,这样会提高效率,避免了客户端和服务器端频繁的发生交互。所以需要一个批处理。但是默认情况下,都会采用批处理,它会生成一个Batch的批处理对象。看一下dwr.engine.beginBatch源码: 

 

dwr.engine.beginBatch = function() {   
  if (dwr.engine._batch) {   
    dwr.engine._handleError(null, { name:"dwr.engine.batchBegun", message:"Batch already begun" });   
    return;   
  }   
  dwr.engine._batch = dwr.engine._createBatch();   
}; 

 

 它也是一个函数,目的就是为了生成一个Batch批处理的对象。生成这个Bactch对象的目的是什么?也就是完成我所需要的操作,操作中的数据都是放在Bactch对象里的,然后通过Bactch来操作,beginBatch需要做的是什么呢?就是如果这个Bactch对象存在的话,就会抛出错误已经存在了,不需要创建,然后直接返回。dwr.engine._batch = 

dwr.engine._createBatch();Batch的创建是通过createBatch()来创建的,createBatch()也是一个函数,看看它的源码:

/** @private Generate a new standard batch */  
dwr.engine._createBatch = function() {   
  var batch = {   
    map:{   
      callCount:0,   
      page:window.location.pathname + window.location.search,   
      httpSessionId:dwr.engine._getJSessionId(),   
      scriptSessionId:dwr.engine._getScriptSessionId()   
    },   
    charsProcessed:0, paramCount:0,   
    parameters:{}, headers:{},   
    isPoll:false, handlers:{}, preHooks:[], postHooks:[],   
    rpcType:dwr.engine._rpcType,   
    httpMethod:dwr.engine._httpMethod,   
    async:dwr.engine._async,   
    timeout:dwr.engine._timeout,   
    errorHandler:dwr.engine._errorHandler,   
    warningHandler:dwr.engine._warningHandler,   
    textHtmlHandler:dwr.engine._textHtmlHandler   
  };   
  if(batch.xml==null)   
  {   
    batch.xml="aaa";   
    }   
  if (dwr.engine._preHook) batch.preHooks.push(dwr.engine._preHook);   
  if (dwr.engine._postHook) batch.postHooks.push(dwr.engine._postHook);   
  var propname, data;   
  if (dwr.engine._headers) {   
    for (propname in dwr.engine._headers) {   
      data = dwr.engine._headers[propname];   
      if (typeof data != "function") batch.headers[propname] = data;   
    }   
  }   
  if (dwr.engine._parameters) {   
    for (propname in dwr.engine._parameters) {   
      data = dwr.engine._parameters[propname];   
      if (typeof data != "function") batch.parameters[propname] = data;   
    }   
  }   
  return batch;   
};  

 里面有很多信息,重要的就是Batch这个变量,里面定义了很多内容。如果对javascript不是很了解,就会感到很茫然,为什么这么说呢?请看下面定义的形式: 

var batch = {   
    map:{   
      callCount:0,   
      page:window.location.pathname + window.location.search,   
      httpSessionId:dwr.engine._getJSessionId(),   
      scriptSessionId:dwr.engine._getScriptSessionId()   
    },   
    charsProcessed:0, paramCount:0,   
    parameters:{}, headers:{},   
    isPoll:false, handlers:{}, preHooks:[], postHooks:[],   
    rpcType:dwr.engine._rpcType,   
    httpMethod:dwr.engine._httpMethod,   
    async:dwr.engine._async,   
    timeout:dwr.engine._timeout,   
    errorHandler:dwr.engine._errorHandler,   
    warningHandler:dwr.engine._warningHandler,   
    textHtmlHandler:dwr.engine._textHtmlHandler   
  };  
 这里面定义的形式类似于一个键一个值(举例textHtmlHandler键:dwr.engine._textHtmlHandler值),这也是javascript中创建一个对象的一种方式,我们也可以通过这种方式来创建,我们可以把这种方式想象成一个键对应一个值,这就是一个对象当中的属性和属性对应的值。也可以想象成dom编程的方式,也就是文档对象模型,为什么可以想象成文档对象模型呢,这就是元素和元素中的内容。怎么想象都可以,但是这种方式我们要注意学习学习。说说里面的内容,创建batch(批处理),批处理可能很多次都要调用到,所以需要一个变量callCount:0指定批处理中需要调用多少次,初始化为0;page是指定请求的页面,window.location.pathname只的是请求的路径,window.location.search指的是路径问号(?)后面的信息; httpSessionId就是JSESSIONID;scriptSessionId 脚本SessionId 
分享到:
评论

相关推荐

    dwr源码分析

    ### DWR源码分析与应用解析 #### DWR框架简介 DWR,全称为Direct Web Remoting,是一款轻量级的远程调用框架,旨在简化Web应用中的JavaScript与Java之间的通信。通过DWR,开发者可以直接从JavaScript调用服务器端...

    dwr demo dwr简单使用

    DWR (Direct Web Remoting) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行交互,实现动态的Web应用。DWR简化了AJAX(Asynchronous JavaScript and XML)的开发,使得开发者可以像调用...

    DWR的技术分析与界面开发

    在这个压缩包中,包含了一系列关于DWR技术分析、学习资料以及相关的界面开发内容,对于理解和掌握DWR技术至关重要。 首先,DWR的XML配置文件是连接客户端与服务器端的关键,它定义了哪些Java对象和方法可以被...

    dwr dwrdwr

    dwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwr

    ajax dwr 框架实现二级联动下拉列表源码

    通过分析这些文件,我们可以深入了解DWR如何与HTML、JavaScript配合,实现实时的数据交互和二级联动下拉列表的功能。 总结来说,利用Ajax和DWR框架实现的二级联动下拉列表,使得用户可以在不刷新页面的情况下完成...

    dwr框架实现二级菜单联动

    在IT领域的开发中,利用DWR(Direct Web Remoting)框架结合Ajax技术实现二级菜单的联动,是一项常见的功能需求,尤其是在动态网页应用中。本文将深入解析如何在包含Spring、Hibernate、Ajax、DWR等技术栈的项目中,...

    DWR 实例 + DWR 深入 (源代码分析).doc

    DWR (Direct Web Remoting) 是一个开源框架,它允许JavaScript在浏览器端直接调用Java方法,从而实现AJAX的应用。DWR的核心功能是通过自动转换Java对象为JavaScript对象,使得前端可以像操作本地对象一样操作远程...

    dwr入门例子 包含类型转换

    Direct Web Remoting (DWR) 是一个开源的Java库,它允许在Web应用程序中实现实时的Ajax通信。DWR简化了JavaScript与服务器端Java对象之间的交互,使得开发者可以像调用本地方法一样调用远程服务。在这个入门例子中,...

    dwr笔记 dwr自学资料

    二、DWR工作原理 1. **反向Ajax**:DWR实现了一种反向Ajax(Reverse Ajax)技术,使得服务器能够主动向客户端推送数据,而不仅仅是响应客户端的请求。 2. **JavaScript与Java的桥接**:DWR通过动态生成JavaScript库...

    dwr中文文档pdf格式

    DWR的使用流程** 1. **引入DWR库**:在Web应用中添加DWR的JAR文件,并在Web.xml中配置DWR的Servlet。 2. **创建Java接口**:定义要在客户端使用的Java接口,这些接口将被DWR暴露给JavaScript。 3. **生成配置文件**...

    dwr.jar 以及dwr配置文件

    同时,DWR提供了丰富的API和工具,简化了前后端的交互流程,提高了开发效率。 在实际项目中,将dwr.jar添加到项目的类路径中,然后在web.xml中配置DWR的servlet,最后根据项目需求调整dwr.xml文件,就可以开始利用...

    Dwr例子带注释

    4. **DWR的运行流程**: - 浏览器加载HTML页面,执行JavaScript代码。 - JavaScript通过DWR发起HTTP请求到服务器。 - DWR Engine接收到请求后,根据`dwr.xml`配置调用相应的Java方法。 - 服务器执行Java方法,...

    DWR3.0.jar、DWR.war和DWR2.0中文说明文档

    通过分析这个war文件,开发者可以学习如何配置DWR的XML配置文件(dwr.xml),以及如何创建可从JavaScript调用的Java方法。 3. **DWR2.0中文说明文档**: 这份文档对于理解DWR的工作原理和使用方法至关重要,特别是...

    dwr练习实例(各种数据转换list,map,数组等)

    Direct Web Remoting (DWR) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行交互,实现Ajax应用。这个"dwR练习实例(各种数据转换list,map,数组等)"是一个用于学习DWR如何处理和转换不同...

    DWR中文文档DWR

    DWR(Direct Web Remoting)是一种Java库,它允许JavaScript在客户端与服务器端进行直接的交互,从而实现在Web应用程序中的Ajax功能。DWR的主要目标是简化前后端的数据交换,提高用户体验,使得Web应用能够像桌面...

    DWR中文教程(外带DWR包)

    3. **DWR映射**:学习如何定义`dwr.xml`配置文件,将前端JavaScript对象映射到后端Java类和方法,这是DWR工作流程的关键部分。 4. **基本使用**:教程可能会涵盖如何创建第一个DWR调用,包括异步和同步调用,以及...

    DWR配置文件详解,DWR配置

    **DWR配置文件详解** Direct Web Remoting (DWR) 是一种开源的Java库,它允许Web应用程序在客户端JavaScript和服务器端Java之间进行双向通信。DWR的核心配置文件是`dwr.xml`,该文件定义了DWR允许访问的Java对象、...

    DWR笔记 DWR.xml配置文件说明书 DWR技术分析

    **DWR技术分析** 1. **异步通信**:DWR利用AJAX技术实现页面无刷新更新,用户可以即时看到服务器端的反馈,提升了交互体验。 2. **安全控制**:DWR提供了安全性控制机制,例如使用白名单限制可调用的Java方法,...

Global site tag (gtag.js) - Google Analytics