DWR工作流程简单来说,
例子中jsp中引入/DWRDemo/dwr/interface/dwrDate.js文件中,方法都是调用 _execute方法,框架封装了_sendData发送ajax请求,后台返回JS代码,前端解析,在调用_remoteHandleCallback方法,执行我们写的回调方法;
dwrDate.getYear = function(callback) {
dwr.engine._execute(dwrDate._path, 'dwrDate', 'getYear', callback);
}
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- 这三个js导入项必不可少 -->
<!-- 每一个对象都会有以一个对象为名称的那个js库 -->
<!-- Dwr 引擎库 -->
<script type='text/javascript' src='/DWRDemo/dwr/engine.js'></script>
<!-- Dwr 工具库 -->
<script type='text/javascript' src='/DWRDemo/dwr/util.js'></script>
<script type="text/javascript" src="/DWRDemo/dwr/interface/dwrDate.js"></script>
<script>
window.onload = function(){
dwrDate.getYear(function(data){
document.getElementById("showTime").innerHTML += 1900 + data + " 年 ";
});
dwrDate.getMonth(function(data){
document.getElementById("showTime").innerHTML += 1 + data + " 月 ";
});
};
</script>
</head>
<body>
<div id="showTime">当前时间:</div>
</body>
</html>
记录下我今天分析的代码:
1.singleShot我理解为一个控制批量发送请求的标志位,true表示不批量发送; |
2.arguments参数为方法传入的参数 |
3.所有_execute()方法入参由dwr自动生成,最后一个参数默认为回调的方法,存储在callData的callback属性中,也会保存在handlers[0]的callback属性里,后面回调就是调的这个callback |
4.传递的参数中包含这样的参数 c0-scriptName=dwrDate 不使用批量发送的话每次参数都以c0-开头,因为每次发送都会new一个新的batch对象,callCount都会从0开始重新增加 |
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();
};
createBatch之后singleShot已经变为true,进入endBatch方法:
endBatch()方法
首先进行了一些校验工作,dwr.engine._batch不能为空、batch.map.callCount不能为零,如果传入了参数options,options是个对象,支持参数有:rpcType、 httpMethod、async、timeout、errorHandler,、warningHandler、textHtmlHandler,请求消息头、方法参数等,这样可以实现局部的个性化,其他方法调用不会引起误会。_ordered属性是用来控制是否严格按照顺序来发送请求得到响应;通过_sendData(batch)发送ajax请求。 |
dwr.engine.endBatch = function(options) {
var batch = dwr.engine._batch;
if (batch == null) {
dwr.engine._handleError(null, { name:"dwr.engine.batchNotBegun", message:"No batch in progress" });
return;
}
dwr.engine._batch = null;
if (batch.map.callCount == 0) return;
// The hooks need to be merged carefully to preserve ordering
if (options) dwr.engine._mergeBatch(batch, options);
// In ordered mode, we don't send unless the list of sent items is empty
if (dwr.engine._ordered && dwr.engine._batchesLength != 0) {
dwr.engine._batchQueue[dwr.engine._batchQueue.length] = batch;
}
else {
dwr.engine._sendData(batch);
}
};
sendData方法太占篇幅就不贴代码了;
_sendData方法主要就是ajax发送请求,置于推送模式,暂时没能力分析,ajax异步请求状态改变事件为dwr.engine._stateChange(); 接收到响应类似这样;通过 if (toEval != null) toEval = toEval.replace(dwr.engine._scriptTagProtection, ""); eval函数调用了eval()方法来解析响应的JS字符串,并执行该方法dwr.engine._remoteHandleCallback,里面就会执行我们写入的回调函数了 |
throw 'allowScriptTagRemoting is false.';
//#DWR-INSERT
//#DWR-REPLY
dwr.engine._remoteHandleCallback('0','0',118);