一、概念
DWR(Direct Web Remoting),中文翻譯成“直接Web遠程控制”。我認為就是將AJAX作了一次封裝,并提供與服務器端Java組件進行交互的一個組件。在其官方網站(http://getahead.ltd.uk/dwr)上說得很清楚,“DWR is Easy Ajax for Java”。DWR允許客戶端的javascript與服務器端的Java進行交互,并根據其交互結果,控制網頁的表現。
說的更明白一些,實際上我的感覺DWR就是在客戶端用Javascript來調用服務器端的Java服務。
技術上,DWR是基于Java,自動生成javascript代碼發送到客戶端,而這些javascript代碼則使用AJAX技術,接受用戶請求,與服務器交互。
二、配置
要使用DWR,需要有兩個配置(當然了,前提要將dwr.jar放在classpath中):
?1.在web.xml中加入如下Servlet信息:
?1
<
servlet
>
?2
???
<
servlet-name
>
dwr-invoker
</
servlet-name
>
?3
???
<
display-name
>
DWR?Servlet
</
display-name
>
?4
???
<
servlet-class
>
uk.ltd.getahead.dwr.DWRServlet
</
servlet-class
>
?5
???
<
init-param
>
?6
????
<
param-name
>
debug
</
param-name
>
?7
????
<
param-value
>
true
</
param-value
>
?8
???
</
init-param
>
?9
??
</
servlet
>
10
11
??
<
servlet-mapping
>
12
???
<
servlet-name
>
dwr-invoker
</
servlet-name
>
13
???
<
url-pattern
>
/dwr/*
</
url-pattern
>
14
??
</
servlet-mapping
>
如此,則將所有的/dwr/開頭的URL請求,影射到dwr-invoker這個Servlet去處理。
?2.在web.xml的同一個目錄下,建立dwr.xml配置文件,在其中配置dwr組件信息,具體內容將在使用一節中講到。
三、使用
?1.一個簡單的例子:
??例如服務器端提供了一個POJO,叫做com.lingdot.dwrtest.TestBean,代碼如下:
?
??
package
?com.lingdot.dwrtest;
??
public
?
class
?TestBean
??{
???
public
?
int
?sum(
int
?a,
int
?b)
???{
????
return
?a
+
b;
???}
??}
?
??在dwr.xml中,作如下配置:
??
<
dwr
>
????
<
allow
>
???
<
create?
creator
="new"
?javascript
="Demo"
>
?????
<
param?
name
="class"
?value
="com.lingdot.dwrtest.TestBean"
/>
???
</
create
>
????
</
allow
>
??
</
dwr
>
?
??Reload這個應用,然后在瀏覽器中打開URL:http://localhost:8080/dwr/(假設當前應用是Tomcat的ROOT應用)。
?
?這個頁面將dwr.xml中配置的Java服務都列了出來。當前我們只配置了一個TestBean。點擊TestBean,出來的頁面會教你如何調用這個Bean的方法。
?
?例如我們的TestBean提供了int sum(int a,intb)這樣的方法,那么,在頁面上:
1.包含如下三個js:
<
script?
type
='text/javascript'src='/DWR/dwr/interface/Demo.js'></script>
<script?type
='text/javascript'?
src
='/DWR/dwr/engine.js'></script>
<script?type
='text/javascript'?
src
='/DWR/dwr/util.js'></script>
?
其中第三個js是可選的,一個工具集。
?2.寫如下代碼:
??
<
input?
type
="button"
?value
="1+2=?"
?onclick
="Demo.sum(1,2,reply0);"
/>
<
div?
id
="m"
></
div
>
<
script
>
?var?reply0?=?function(data)
????{
??????if?(data?!=?null?&&?typeof?data?==?'object')
alert(DWRUtil.toDescriptiveString(data,?2));
??????else
DWRUtil.setValue('m',?DWRUtil.toDescriptiveString(data,?1));
????}
</
script
>
?
注意,其中button上的onclick事件調用的是Demo對象的sum方法。而Demo對象是由我們在dwr.xml中配置的一個create節點中寫的javascript=”Demo”屬性而來的。
再注意,Demo的sum方法其實就是我們的TestBean的sum方法,但是,在參數列表的最后,新加了一個變量,叫做reply0。緊接著在下面的script代碼中我們定義了這個reply0是一個函數,這個函數的功能就是如果所提供的data不為空,那么,就把它顯示到一個id為”m”的html元素內部。而這個id為“m”的元素在文檔中已經定義為一個div元素。由此,Demo的sum方法執行的時候實際上是調用服務器端的TestBean的sum方法,并返回結果,作為data參數,傳遞給reply0方法去處理,而處理的結果,就是在id=”m”的div元素內部顯示出來。
四、需要注意的兩個問題
?1. Warning: No Converter for XXX.
dwr.xml does not have an allow entry that enables conversion of this type to Javascript. The most common cause of this problem is that XXX is a java bean and bean marshalling has not been enabled. Bean marshalling is disabled by default for security reasons.
To enable marshalling for a given bean add the following line to the allow section of your dwr.xml file:
<convert converter="bean" match="XXX"/>
It is also possible to enable marshalling for an entire package or hierachy of packages using the following:
<convert converter="bean" match="package.name.*"/>
2.不要重載方法
五、一些方法
1.?DWRUtil.setValue('d0', DWRUtil.toDescriptiveString(data, 1));
DWRUtil.setValue() is a utility that takes the data you pass in the second parameter and works out how to fit it to go into the HTML element specified by id in the first parameter. This function is one of several neat Javascript utilities that make working with DWR much easier.
第一個參數是要顯示內容的元素的id,如上面的例子中的m是一個div的id,第二個參數是要顯示的內容
2.?方法參數以及回調函數的幾種寫法:
Demo.sum(1,2,{callback:function(str) { alert(str); },
? timeout:5000,
? errorHandler:function(message) { alert('Oops: ' + message); }
});
Remote.getData(42, function(str) { alert(str); });
3.?建立javascript對象,對應java的對象,例如:
在Java中有一個Remote類,其中的方法setPerson參數是Person類的一個對象,Java代碼如下:
public
?
class
?Remote?{
??
public
?
void
?setPerson(Person?p)?{
????
this
.person?
=
?p;
??}
}
public
?Person?{
??
private
?String?name;
??
private
?
int
?age;
??
private
?Date[]?appointments;
??
//
?getters?and?setters?
}
那么,在Javascript中可以這樣寫:
?4. DWRUtil.useLoadingMessage(); 顯示正在更新數據的標志
var?p?
=
?{???
//
建立與java的Person類對應的js對象
??name:
"
Fred?Bloggs
"
,
??age:
42
,
??appointments:[?
new
?Date(),?
new
?Date(
"
1?Jan?2008
"
)?]
};
Remote.setPerson(p);