`
zyslovely
  • 浏览: 231581 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

深入分析DWR的Engine._execute方法

阅读更多
DWREngine 作为dwr客户端的stub,_execute是其核心方法

正因为是stub,所以你几乎不会直接使用这个方法,通常你会在服务器的dwr.xml定义需要暴露的service及其可调用方法,dwr会根据这个配置文件自动生成一个js文件,对应你暴露的service及其方法,你会在本地调用js文件定义的方法,和调用java的方法一样,除了多了一个回调参数,然后这个方法会委托DWREngine._execute发出请求

/**

* @private Send a request. Called by the Javascript interface stub

* @param path part of URL after the host and before the exec bit without leading or trailing /s

* @param scriptName The class to execute

* @param methodName The method on said class to execute

* @param func The callback function to which any returned data should be passed

*

if this is null, any returned data will be ignored

* @param vararg_params The parameters to pass to the above class

*/

//函数定义

DWREngine._execute = function(path, scriptName, methodName, vararg_params) {

//定义标记,由此标记才能发请求

var singleShot = false;



//实例化一个_batch封装请求

if (DWREngine._batch == null) {

DWREngine.beginBatch();

singleShot = true;

}

// To make them easy to manipulate we copy the arguments into an args array

//定义一个数组存储远程方法请求的参数,通常情况下第一个是回调函数,后面才是与远程方法对应的//形参

var args = [];



//从函数参数的第4个开始算,因为前3个不算,前3个分别是服务器端的请求路径,远程服务脚本名,//远程服务的方法

for (var i = 0; i < arguments.length - 3; i++) {

args[i] = arguments[i + 3];

}



//设置请求路径

// All the paths MUST be to the same servlet

if (DWREngine._batch.path == null) {

DWREngine._batch.path = path;

}

else {

if (DWREngine._batch.path != path) {

DWREngine._handleError("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 params;

//定义变量代表本地回调函数

var callData;

//取出请求参数的第一个,通常是回调函数

var firstArg = args[0];

//取出最后一个,通常是远程方法的参数(一般情况下,除了第一个其他都是)

var lastArg = args[args.length - 1];



//1)如果第一个参数函数,那么进入if块

if (typeof firstArg == "function") {

//实例化callData,然后将请求参数数组的第一个赋给callData,并将第一个参数踢出数组

//也就说此时的请求参数数组是纯粹的远程方法的参数数组

callData =

//将剔除了回调函数的请求参数数组赋给params

params = args;

}

//2)也许你会采用这种格式即最后一个是回调函数,其他是远程方法参数,那么下个面的if块适合你

else if (typeof lastArg == "function") {

callData =

params = args;

}

//3)如果你将最后一个请求参数定义为对象且为其设置了callback方法,那么那么下面的if块适合你

else if (typeof lastArg == "object" && lastArg.callback != null && typeof lastArg.callback == "function") {

callData = args.pop();

params = args;

}

//4)如果第一个参数为空,那么进入下面的块

else if (firstArg == null) {

// This could be a null callback function, but if the last arg is also

// null then we can't tell which is the function unless there are only

// 2 args, in which case we don't care!



//如果最后一个参数也为空,但参数大于2,那么就会报错,因为系统不知道到底那一个才是//空的回调函数

if (lastArg == null && args.length > 2) {

if (DWREngine._warningHandler) {

DWREngine._warningHandler("Ambiguous nulls at start and end of parameter list. Which is the callback function?");

}

}

callData =

params = args;

}

//5)第一参数不为空,最后一个为空,那么将最后一个参数之外的所有参数视为远程方法参数

else if (lastArg == null) {

callData =

params = args;

}

//6)以上情况都不成立,抛错

else {

if (DWREngine._warningHandler) {

DWREngine._warningHandler("Missing callback function or metadata object.");

}

return;

}



//通常还是将第一作为回调函数,后面全部是远程方法参数,如果无需回调,第一个为null

//好不容易分开了回调函数很远程请求参数,继续前进



// Get a unique ID for this call

//产生随机数作为请求ID

var random = Math.floor(Math.random() * 10001);

var + "_" + new Date().getTime()).toString();

//定义一个前缀变量

var prefix = "c" + DWREngine._batch.map.callCount + "-";

//将请求ID存入请求对象的ID数组

DWREngine._batch.ids.push(id);



//如果你是将一个对象而非函数作为回调函数,见上面的第3种情况,那么一下一段代码适合你,否则//跳过

// batchMetaData stuff the we allow in callMetaData for convenience



//设置_batch的method属性

if (callData.method != null) {

DWREngine._batch.method = callData.method;

delete callData.method;

}



//设置_batch的verb 属性

if (callData.verb != null) {

DWREngine._batch.verb = callData.verb;

delete callData.verb;

}

//设置_batch的async 属性

if (callData.async != null) {

DWREngine._batch.async = callData.async;

delete callData.async;

}

////设置_batch的timeout 属性

if (callData.timeout != null) {

DWREngine._batch.timeout = callData.timeout;

delete callData.timeout;

}

//如果callData存在preHook ,那么将此preHook 加入_batch的preHook数组的第一个

// callMetaData stuff that we handle with the rest of the batchMetaData

if (callData.preHook != null) {

DWREngine._batch.preHooks.unshift(callData.preHook);

delete callData.preHook;

}

//如果callData存在postHook ,那么将此preHook 加入_batch的postHooks数组的最后一个

if (callData.postHook != null) {

DWREngine._batch.postHooks.push(callData.postHook);

delete callData.postHook;

}



// Default the error and warning handlers

//设置错误处理器和警告处理器

if (callData.errorHandler == null) callData.errorHandler = DWREngine._errorHandler;

if (callData.warningHandler == null) callData.warningHandler = DWREngine._warningHandler;



// Save the callMetaData

//将回调函数放入_handlersMap对象中,以id作为key或属性

DWREngine._handlersMap[id] = callData;



//设置_batch的map对象

    //设置脚本属性

DWREngine._batch.map[prefix + "scriptName"] = scriptName;

    //设置方法属性

DWREngine._batch.map[prefix + "methodName"] = methodName;

    //设置id属性

DWREngine._batch.map[prefix + "id"] = id;



// Serialize the parameters into batch.map

//为DWREngine添加编码函数

DWREngine._addSerializeFunctions();



//将远程方法参数编码为某种格式

//以下是几种格式的例子

//比如一个一个js字符串的值为323YN2O2,那么编码后成为 "string:323YN2O2"

//比如一个对象编码为"Object:{tvUserId:reference:c0-e6, userNo:reference:c0-e7, loginName:reference:c0-e8}"


//编码全部存入_batch的map对象

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

DWREngine._serializeAll(DWREngine._batch, [], params[i], prefix + "param" + i);

}



//删除DWREngine刚刚添加的编码函数

DWREngine._removeSerializeFunctions();



// Now we have finished remembering the call, we incr the call count

//调用此数加1

DWREngine._batch.map.callCount++;

//标记为true,发送请求

if (singleShot) {

DWREngine.endBatch();

}

};



总结:_execute其实只干了两件事情

1)分离回调函数和远程方法参数

2)编码远程方法参数



最后再调用另一个很重要的函数endBatch(其实是_sendData)来完成请求



从_execute方法可以看出DWREngine有个很重要的数据结构就是_batch

_batch可以视为请求参数的封装器,其实比这更多

它包含以下几个属性

字符数组),map(对象)(主要包含c0-id.c0-methodName,c0-scriptName,callCount,c0-paramx(x为0或1或2,有几个参数就有几个paramx ),还包含很多细小的参数对象的属性编码,每个编码都为一个属性),paramCount(数值),path(字符串),preHooks(函数数组),postHooks(函数数组)


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=875971
分享到:
评论

相关推荐

    dwr包.rar dwr.jar engine.js util.js dwr-noncla.jar readme.txt

    dwr包.rar dwr.jar engine.js util.js dwr-noncla.jar readme.txt JAR File: dwr.jar (1.08Mb) To DWR enable your web-app WAR File: dwr.war (4.62Mb) Demos/Examples of what DWR can do Sources: dwr-...

    dwr.rar_dwr jar_dwr j_dwr jar_dwr.j_dwr.jar2

    **dwr.jar**是DWR的核心库,包含了许多关键类和接口,如`AjaxEngine`、`CallContext`以及`ReverseAjax`等。这些类为建立AJAX请求提供了基础框架。`AjaxEngine`负责处理客户端的AJAX请求,并将它们转发到相应的服务器...

    DWR(包括engine.js+util.js).rar

    为了使用DWR,开发者需要在服务器端配置DWR引擎,定义允许访问的Java类和方法,并在客户端引入`engine.js`和`util.js`。然后,通过JavaScript代码就可以直接调用服务器端的方法,实现双向通信。 总之,DWR提供了一...

    ssh(dwr).rar_DWR SSH_dwr_java dwr_ssh_ssh dwr

    DWR的配置文件(通常为dwr.xml)定义了哪些Java类和方法可以被远程调用。 在这个示例中,可能会包含以下内容: 1. **源代码**:这可能包括一个简单的Web应用,含有DWR的配置文件,以及使用JSch和DWR进行交互的Java...

    dwr util.js engine.js

    在开发过程中,如果不想去dwr.jar中寻找这些文件,可以直接下载这个压缩包,这样就可以快速地在项目中引入DWR的功能,实现前后端的高效通信。记住,引入DWR后,还需要正确配置Web应用的`web.xml` 文件以及服务器端的...

    DWR_comet_0100.zip_ChatService.js_DWR_comet_0100_comet_dwr SPRIN

    在JavaScript中,DWR提供了简单的API来封装与服务器的通信,如`dwr.engine.remote.handleCallback()`函数,用于处理从服务器返回的结果。`ChatService.js`可能定义了用于发送聊天消息、接收新消息和更新聊天界面的...

    ext2+spring+hibernate+dwr.rar_dwr MenuManage.js_ext2 ja

    标题 "ext2+spring+hibernate+dwr.rar_dwr MenuManage.js_ext2 ja" 提示我们这是一个关于集成技术的项目,其中包含了ext2、Spring、Hibernate和DWR(Direct Web Remoting)四个主要组件。这个项目的具体实现是通过...

    dwr教程+dwr.jar+util.js+engine.js

    `dwr.xml` 文件是DWR的配置文件,用于设置DWR的行为,如允许访问的Java类和方法、安全性设置、错误处理等。通过编辑这个文件,开发者可以控制哪些服务器端的对象和方法可以被AJAX调用,以及如何处理这些调用。此外,...

    dwr.rar_dwr_dwr Stri_dwr javabean

    在这个"**dwr.rar_dwr_dwr Stri_dwr javabean**"的压缩包中,我们可能找到了关于DWR如何处理不同类型数据的详细信息,特别是对String、list、map以及JavaBean的操作。 首先,让我们深入理解DWR的核心概念。DWR的...

    dwrTest.rar_dwr 3 jar_dwr jar_dwr2.0 jar

    2. **配置DWR**:在Web应用的WEB-INF目录下创建dwr.xml配置文件,定义允许客户端访问的服务器端方法。 3. **创建Java类和方法**:在服务器端编写需要暴露给客户端调用的Java类和方法。 4. **生成JavaScript接口**:...

    dwr.rar_dwr_dwr ajax_dwr 实现 联动 标签

    在“dwr.rar_dwr_dwr ajax_dwr 实现 联动 标签”这个项目中,我们将探讨如何利用DWR和AJAX技术来创建一个动态的、具有联动效果的标签系统。 1. **DWR基础**: DWR的核心组件包括一个服务器端的Servlet(DWR Engine...

    Dwr.rar_dwr_dwr jsp_jsp d_jsp dwr

    在这个"Dwr.rar_dwr_dwr jsp_jsp d_jsp dwr"的实例中,我们将探讨如何将DWR集成到JSP(JavaServer Pages)项目中,以及这种集成可以带来的好处和实现方式。 首先,DWR的核心功能是创建了一个安全的、跨域的AJAX...

    dwr20.dtd

    dwr20.dtd

    dwr.zip_dwr_encryption_mvc_加密

    标题中的“dwr.zip_dwr_encryption_mvc_加密”暗示了这是一个关于Direct Web Remoting (DWR)、加密技术和MVC(Model-View-Controller)框架的项目或示例。DWR是一种允许在JavaScript和Java之间进行安全、动态通信的...

    dwr.jar engine.js util.js,Dwr相关

    标题中的"dwr.jar"是DWR的主要库文件,包含了所有必要的Java类和接口,用于在服务器端实现DWR的功能。这个JAR文件通常会被部署到应用服务器的类路径中,以便服务端代码可以访问和使用DWR的API。 "engine.js"是DWR的...

    dwr_test.zip_dwr_dwr test index_dwr test 语法

    这通常在`dwr.xml`配置文件中完成。 2. **映射**:定义JavaScript接口,这些接口对应服务器上的Java类。这些接口使JavaScript代码能够调用服务器端的方法。 3. **安全性**:DWR提供了安全特性,如CSP(Content ...

    dwr3.0.jar_ajax

    这个JAR文件是DWR的核心组件,包含了所有必需的类和资源,使得开发者可以在服务器端与JavaScript进行交互,实现异步更新和远程调用Java对象的方法。 描述中提到的“dwr3.0.zip包括dwr3.0的jar包和war运行文件”,...

    spring+dwr.rar_dwr_dwr SPRING_spring dwr

    3. **暴露Java服务给DWR**:在DWR的配置文件(通常是`dwr.xml`)中,我们需要声明要公开给JavaScript的Java类和方法。这可以通过`&lt;create&gt;`标签完成,指定Java类和暴露的方法。 4. **编写前端JavaScript**:在HTML...

    dwr20.dtd约束文件

    dwr20.dtd约束文件。 &lt;!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr/dwr20.dtd" &gt;

    dwr.rar_dwr_dwr tutorial

    这个"**dwr.rar_dwr_dwr tutorial**"压缩包显然包含了一份高质量的DWR教程,可以帮助学习者在短短一周内从零基础到能够将DWR应用于实际项目。下面,我们将深入探讨DWR的关键概念和应用场景。 **1. DWR的核心功能:*...

Global site tag (gtag.js) - Google Analytics