看一下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的xml配置文件说明,DWR学习笔记,DWR技术分析,DWR开发培训,WEB界面开发规范,还有一些重要控件的代码分析和文档说明,如树控件。
dwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwrdwr dwr
dwr的简单使用,是一个Eclipse的项目,直接导进去就可以看到使用的方式了 对于初学者这个应该是不错的demo哦~
dwr 框架dwr 框架dwr 框架dwr 框架dwr 框架dwr 框架
dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;dwr包;
dwr入门例子 包含类型转换 dwr实战.doc
DWR 实例 + DWR 深入 (源代码分析).doc dwr学习的实例
DWR开发流程,ajax很好的开发辅助工具,每步很详细,完全傻瓜操作指南
DWR中文文档DWR中文文档DWR中文文档DWR中文文档DWR中文文档
DWR笔记 DWR.xml配置文件说明书 DWR技术分析
dwr源码
ajax技术中利用dwr框架实现二级联动菜单,页面无刷新
dwr笔记 dwr自学资料 dwr笔记 dwr自学资料 dwr笔记 dwr自学资料
dwr中文文档dwr中文文档dwr中文文档dwr中文文档dwr中文文档dwr中文文档dwr中文文档
DWR介绍DWR介绍DWR介绍DWR介绍DWR介绍DWR介绍
Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr入门操作手册Dwr...
DWR配置文件详解 DWR配置 DWR配置文件
dwr实现的完整的二级下拉联动列表,里面有说明,源代码。
配置dwr组件到dwr.xml文件中,如果有必要,配置convert,进行java和javascript类型互转。 5.通过反射机制,dwr将步骤4的类转换成javascript代码,提供给前台页面调用。 5.编写网页,调用步骤5的javascript中的相关...