<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更为合适