????<servlet>
????????<servlet-name>dwr-invoker</servlet-name>
????????<display-name>DWR Servlet</display-name>
????????<description>Direct Web Remoter Servlet</description>
????????<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
????????<init-param>
????????????<param-name>debug</param-name>
????????????<param-value>true</param-value>
????????</init-param>
????</servlet>
????<servlet-mapping>
????????<servlet-name>dwr-invoker</servlet-name>
????????<url-pattern>/dwr/*</url-pattern>
????</servlet-mapping>
一個可選的步驟是設置DWR為調試模式—象上面的例子那樣—在servlet描述段中將debug參數設為true。當DWR在調試模式時,你可以從HTMl網頁中看到所有的可訪問的Java對象。包含了可用對象列表的網頁會出現在/WEBAPP/dwr這個url上,它顯示了對象的公共方法。所列方法可以從頁面中調用,允許你,第一次,運行服務器上的對象的方法。下圖顯示了調試頁的樣子:

調試頁
現在你必須讓DWR知道通過XMLHttpRequest對象,什么對象將會接收請求。這個任務由叫做dwr.xml的配置文件來完成。在配置文件中,定義了DWR允許你從網頁中調用的對象。從設計上講,DWR允許訪問所有公布類的公共方法,但在我們的例子中,我們只允許訪問幾個方法。下面是我們示例的配置文件:
<dwr>
????<allow>
????????<convert converter="bean" match="dwr.sample.Apartment"/>
????????<create creator="new" javascript="ApartmentDAO" class="dwr.sample.ApartmentDAO">
????????????<include method="findApartments"/>
????????????<include method="countApartments"/>
????????</create>
????</allow>
</dwr>
上面的文件實現了我們例子中的兩個目標。首先,<convert>標記告訴DWR將dwr.sample.Apartment對象的類型轉換為聯合數組,因為,出于安全的原因,DWR默認的不會轉換普通bean。第二,<create>標記讓DWR暴露出dwr.sample.ApartmentDAO類給JavaScript調用;我們在頁面中使用JavaScript文件被javascript屬性定義。我們必須注意<include>標記,它指明了dwr.sample.ApartmentDAO類的哪些方法可用。
HTML/JSP代碼
配置完成后,你就可以啟動你的Web應用了,這時DWR會為從你的HTML或Java服務器端頁面(JSP)上調用所需方法作好準備,并不需要你創建JavaScript文件。在search.jsp文件中, 我們必須增加由DWR提供的JavaScript接口,還有DWR引擎,加入以下三行到我們的代碼中:
??<script src='dwr/interface/ApartmentDAO.js'></script>
??<script src='dwr/engine.js'></script>
??<script src='dwr/util.js'></script>
我們注意到當用戶改變搜索標準時,這是AJAX在示例程序中的首次應用;正如他所看到的,當標準改變時,可用的公寓數量被更新了。我創建了兩個JavaScript函數:當某一個選擇下拉框中的值變化時被調用。ApartmentDAO.countApartments()函數是最重要的部分。最有趣的是第一個參數, loadTotal()函數,它指明了當接收到服務端的返回時DWR將會調用的JavaScript方法。loadTotal于是被調用來在HTML頁面的<div>中顯示結果。下面是在這個交互場景中所使用到的JavaScript函數:
function updateTotal() {
????$("resultTable").style.display = 'none';
????var bedrooms = document.getElementById("bedrooms").value;
????var bathrooms = document.getElementById("bathrooms").value;
????var price = document.getElementById("price").value;
????ApartmentDAO.countApartments(loadTotal, bedrooms, bathrooms, price);
}
function loadTotal(data) {
????document.getElementById("totalRecords").innerHTML = data;
}
很明顯,用戶想看到符合他的搜索條件的公寓列表。那么,當用戶對他的搜索標準感到滿意,并且總數也是有效的話,他會按下顯示結果的按紐,這將會調用updateResults() JavaScript方法:
function updateResults() {
????
????DWRUtil.removeAllRows("apartmentsbody");
????var bedrooms = document.getElementById("bedrooms").value;
????var bathrooms = document.getElementById("bathrooms").value;
????var price = document.getElementById("price").value;
????ApartmentDAO.findApartments(fillTable, bedrooms, bathrooms, price);
????$("resultTable").style.display = '';
}
function fillTable(apartment) {
????DWRUtil.addRows("apartmentsbody", apartment, [ getId, getAddress, getBedrooms, getBathrooms, getPrice ]);
}
updateResults()方法清空了存放搜索返回結果的表域,從用戶界面上獲取所需參數,并且將這些參數傳給DWR創建的ApartmentDAO對象。然后數據庫查詢將被執行,fillTable()將會被調用,它解析了DWR返回的對象(apartment),然后將其顯示到頁面中(apartmentsbody)。
安全因素
為了保持示例的簡要,ApartmentDAO類盡可能的保持簡單,但這樣的一個類通常有一組設置方法來操作數據,如insert(), update()和delete()。DWR暴露了所有公共方法給所有的HTML頁面調用。出于安全的原因,像這樣暴露你的數據訪問層是不明智的。開發者可以創建一個門面來集中所有JavaScript函數與底層業務組件之間的通信,這樣就限制了過多暴露的功能。
結論
這篇文章僅僅讓你在你的項目中使用由DWR支持的AJAX開了個頭。DWR讓你集中注意力在如何提高你的應用的交互模型上面,消除了編寫和調試JavaScript代碼的負擔。使用AJAX最有趣的挑戰是定義在哪里和如何提高可用性。DWR負責了操作Web頁面與你的Java對象之間的通信,這樣就幫助你完全集中注意力在如何讓你的應用的用戶界面更加友好,
我想感謝Mircea Oancea和Marcos Pereira,他們閱讀了這篇文章并給予了非常有價值的返匱。
資源
·javaworld.com:
javaworld.com
·Matrix-Java開發者社區:
http://www.matrix.org.cn/
·onjava.com:
onjava.com
·下載示例程序的全部源碼:
http://www.javaworld.com/javaworld/jw-06-2005/dwr/jw-0620-dwr.war
·DWR: http://www.getahead.ltd.uk/dwr/index.html
·HSQL:http://hsqldb.sourceforge.net/
·AJAX的定義:http://en.wikipedia.org/wiki/AJAX
· “AJAX:通向Web應用的新途徑": Jesse James Garrett (Adaptive Path, 2005.2): http://www.adaptivepath.com/publications/essays/archives/000385.php
· “非常動態的Web界面” Drew McLellan (xml.com, 2005.2): http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
·XMLHttpRequest & AJAX 工作范例: http://www.fiftyfoureleven.com/resources/programming/xmlhttprequest/examples
· “可用的XMLHttpRequest實踐” Thomas Baekdal (Baekdal.com, 2005.3): http://www.baekdal.com/articles/Usability/usable-XMLHttpRequest/
·"XMLHttpRequest使用導引" Thomas Baekdal (Baekdal.com,??2005.2):http://www.baekdal.com/articles/Usability/XMLHttpRequest-guidelines/
·AJAX實質:http://www.ajaxmatters.com/
(看完后個人感覺:有了DWR就JAVA開發而言,完全可以與AJAX匹敵啦,省了在JS上對XMLHTTP以及對DOM的處理,不可以避免地在后臺對應的IO處理;然后就DWR來說,它增加了對XML中對應的配置--在開源框架中似乎一直不曾停止過。還有對一些DWR自有用法如DWRUtil.addRows得參考其相關文檔---當然這樣的功能我們自己也可以用JS來解決,并且它顯然很實用。)
DWRUtil學習
這些功能函數在下面這個網址都有示例,這里只是把他們用中文解釋,方便查找.
http://getahead.ltd.uk/dwr/browser/utilDWRUtil.getText(id)
這個函數只能用于select
getText(id) is similar to getValue(id), except that it is designed for <select ... lists where you need to get the displayed text rather than the value of the current option.
這個函數主要的作用是取到當前select的顯示值即<option value>xxx</option>中xxx的內容
DWRUtil.getValue(id) 用來得到<option value>xxx</option>等元素的value值
DWRUtil.getValue(id) is the read version of setValue(). This gets the values out of the HTML elements without you needing to worry about how a selection list differs from a div.
這個函數能用于多個元素input type =textarea,text,Form button,formbutton,password(明文),
Fancy button等元素,主要可以屏蔽原來對select元素getValue操作帶來的不便
DWRUtil.getValues()
getValues() is similar to getValue() except that the input is a Javascript object that contains name/value pairs. The names are assumed to be the IDs of HTML elements, and the values are altered to reflect the contents of those IDs. This method does not return the object in question, it alters the value that you pass to it.
此函數主要是一次完成多個元素的getValue()操作,并將value的結果以js對象的形式封裝起來返回,參數是一個js對象,其中包含了希望取到value的element id
e.g
{ div:null, textarea:null, select:null, text:null, password:null, formbutton:null, button:null}
詳細參考
http://getahead.ltd.uk/dwr/browser/util/getvalues查看效果
DWRUtil.onReturn
When inputs are part of a form then the return key causes the form to be submitted. When you are using Ajax, this is generally not what you want. Usually it would be far better if some JavaScript was triggered.Unfortunately different browsers handle events in quite a different manner. So DWRUtil.onReturn patches over the differences.
在一個form表單中敲回車鍵將導致表單被遞交,這往往不是我們希望看到的.但是很多瀏覽器對這個事件的處理是不統一的,這個函數就是為了消除這個不統一的
DWRUtil.onReturn(event, submitFunction)
DWRUtil.selectRange
Selecting a range of text in an input box
You need to select text in an input box for any "Google suggest" type functions, however the selection model changes a lot between different browsers. The DWRUtil function to help here is: DWRUtil.selectRange(ele, start, end).
在一個input元素中選擇一個范圍的字符串,可以查看
http://getahead.ltd.uk/dwr/browser/util/selectrange操作
DWRUtil.setValue(id, value)
DWRUtil.setValue(id, value) finds the element with the id specified in the first parameter and alters its contents to be the value in the second parameter.
This method works for almost all HTML elements including selects (where the option with a matching value and not text is selected), input elements (including textareas) divs and spans.
主要是為了設值,屏蔽了select元素設值的問題,對select也可以方便的setvalue
DWRUtil.setValues()
Similar to setValue except that the input is a Javascript object that contains name/value pairs. The names are assumed to be the IDs of HTML elements, and the values, what we should set the contents of the elements.
與getValues對應,傳入js對象,將對象中的value傳給相應的element
DWRUtil.toDescriptiveString(id,degree)
DWRUtil.toDescriptiveString is a better version of the toString() than the default. This function has a third parameter that declares the initial indent. This function should not be used from the outside world as it may well change in the future.
此函數主要用來調試,傳入元素的id,調試的degree將顯示DOM信息
此函數有第三個參數,用于聲明初始化,包含第三個參數的調用不應該為使用,因為這個函數將來會改變
DWRUtil.useLoadingMessage
You must call this method after the page has loaded (i.e. not before the onload() event has fired) because it creates a hidden div to contain the loading message.
你必須在頁面加載完成后(body onload事件)調用這個函數,因為它會創建一個div,來包含一些消息.類似gmail的message模式的東西.為了達到在頁面加載完成后來操作,
http://getahead.ltd.uk/dwr/browser/util/useloadingmessage
提供了一些方法.例如
<script>function init() { DWRUtil.useLoadingMessage();}if (window.addEventListener) { window.addEventListener("load", init, false);}else if (window.attachEvent) { window.attachEvent("onload", init);}else { window.onload = init;}</script>
該參考頁面給出了2個類似的文字圖片實現.
DWRUtil.addOptions() 用返回的集合來填充select元素
多種實現,詳細參考
http://getahead.ltd.uk/dwr/browser/listsDWRUtil.addRows() 返回的集合來填充table元素,或者tbody更為合適?
?