通過前面五章學習,對DWR整體有所了解,但是我仍然對核心細節不是很清楚。我最后的辦法就是單步調試,調試之后將所有東西串一串,DWR的原理就清楚了,搞清楚核心生產線,其他全是輔助的,沒必要再分析了。老外聰明啊,服。
我們以DWR的第一個樣例為例Dynamically Text
1,在index.html里面我們嵌入
<script type='text/javascript' src='../dwr/engine.js'> </script>
<script type='text/javascript' src='../dwr/util.js'> </script>
<script type='text/javascript' src='../dwr/interface/Demo.js'> </script>
前面兩個都是DWR系統默認需要加載的,Demo.js是Demo.java所對應的。按理論,只要在web.xml和dwr.xml配置好,那么我們就可以在客戶端操作Demo.js,類似于操作服務器端的Demo.js。
HTML source:
<p>
Name:
<input type="text" id="demoName"/>
<input value="Send" type="button" onclick="update()"/>
<br/>
Reply: <span id="demoReply"></span>
</p>
Javascript source:
function update() {
var name = dwr.util.getValue("demoName");
Demo.sayHello(name, function(data) {
dwr.util.setValue("demoReply", data);
});
}
Java source:
package org.getahead.dwrdemo.simpletext;
public class Demo {
public String sayHello(String name) {
return "Hello, " + name;
}
}
dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">
<dwr>
<allow>
<create creator="new" javascript="Demo">
<param name="class" value="org.getahead.dwrdemo.simpletext.Demo"/>
</create>
</allow>
</dwr>
在瀏覽器第一次加載本頁面時,瀏覽器第一步發現<script type='text/javascript' src='../dwr/engine.js'> </script>,根據web.xml關于dwr的配置,系統會激發Servlet的POST方法,向客戶端輸出engine.js文件流,這個文件你可以在IE的緩存里面發現,當然,程序會在最后輸出一刻比較客戶端是否已經存在該文件,如果要輸出的文件流大小和和該文件大小一致,就不輸出了,同樣util.js、Demo.js也是這么輸出的。那么看看Demo.js文件里面的內容如下:

if (typeof this['Person'] != 'function')
{

function Person()
{
this.address = null;
this.phoneNumber = null;
this.name = null;
this.id = 0;
this.salary = 0;
}
}

// Provide a default path to dwr.engine

if (typeof this['dwr'] == 'undefined') this.dwr =
{};

if (typeof dwr['engine'] == 'undefined') dwr.engine =
{};


if (typeof this['Demo'] == 'undefined') this.Demo =
{};

Demo._path = '/dwr/dwr';


Demo.sayHello = function(p0, callback)
{
return dwr.engine._execute(Demo._path, 'Demo', 'sayHello', p0, callback);
};


Demo.getInclude = function(callback)
{
return dwr.engine._execute(Demo._path, 'Demo', 'getInclude', callback);
};
這樣我們就知道了,實際上Demo.java類的sayHello方法已經被解釋到Demo.js中了,只不過后面的調用還不是很清楚而已。
繼續!
public String sayHello(String name) {
return "Hello, " + name;
}
翻譯成
Demo._path = '/dwr/dwr';
Demo.sayHello = function(p0, callback) {
return dwr.engine._execute(Demo._path, 'Demo', 'sayHello', p0, callback);
};
在調用engine.execute()方法時,最終采用無刷新訪問服務器技術。
采用該技術的關鍵問題是兩個參數,一個是url,往什么地方發送;一個是doc,發送什么內容
通過跟蹤engine.js我們知道
url=/dwr/dwr/call/plaincall/Demo.sayHello.dwr
發送內容如下:
callCount=1
windowName=DWR-442B435
899
c0-scriptName=Demo
c0-methodName=sayHello
c0-id=0
c0-param0=string:Joe
batchId=1
page=/dwr/simpletext/index.html
httpSessionId=
scriptSessionId=1CC3A
.0A3
實際上url=/dwr/dwr/call/plaincall/Demo.sayHello.dwr,轉向的是DwrServlet,DwrServlet實際上獲取了兩部分信息,一部分是url,根據這個能夠解析到我們的目標java類、方法,另外一部分是發送信息包,實際上這就是SayHello所需要的參數輸入信息,最后,返回數據,這些數據格式通過response返回,在engine.js中對應于return batch.reply;通過解析返回對象,采用javascirpt將數據動態刷新到頁面。
至此,dwr的核心原理,基本清晰