软件艺术思考者  
混沌,彷徨,立志,蓄势...
公告
日历
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

随笔分类(86)

随笔档案(85)

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 

作者:Cloves Carneiro; simmone
原文地址: http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html
中文地址: http://www.matrix.org.cn/resource/article/43/43926_DWR_AJAX.html
关键词: DWR AJAX


概述

这篇文章阐述了使用开源项目DWR(直接Web远程控制)和AJAX(异步JavaScript和XML)的概念来提高Web应用的可用性。作者一步步来展示DWR如何使得AJAX的应用既简单又快捷。(1600字;2005年6月20日)

AJAX,或者说是异步JavaScript和XML,描述了一种使用混合了HTML(或XHTML)和层叠样式表作为表达信息,来创建交互式的Web应用的开发技术;文档对象模型(DOM),JavaScript,动态地显示和与表达信息进行交互;并且,XMLHttpRequest对象与Web服务器异步地交换和处理数据。

因特网上许多例子展示了在一个HTML文件内部使用XMLHttpRequest与服务器端进行交互的必要的步骤。当手工地编写和维护XMLHttpRequest代码时,开发者必须处理许多潜在的问题,特别是类似于跨浏览器的DOM实现的兼容性这样的问题。这将会导致在编码和调试Javascript代码上面花费数不清的时间,这显然对开发者来说很不友好。

DWR(直接Web远程控制)项目是在Apache许可下的一个开源的解决方案,它供给那些想要以一种简单的方式使用AJAX和XMLHttpRequest的开发者。它具有一套Javascript功能集,它们把从HTML页面调用应用服务器上的Java对象的方法简化了。它操控不同类型的参数,并同时保持了HTML代码的可读性。

DWR不是对一个设计的插入,也不强迫对象使用任何种类的继承结构。它和servlet框架内的应用配合的很好。对缺少DHTML编程经验的开发者来说,DWR也提供了一个JavaScript库包含了经常使用的DHTML任务,如组装表,用item填充select下拉框,改变HTML元素的内容,如<div>和<span>
DWR网站是详尽的并且有大量的文档,这也是这篇文章的基础。一些例子用来展示DWR如何使用和用它的库可以完成什么样的工作。

这篇文章让读者看到了一个使用了DWR的Web应用是如何一步步建立的。我会展示创建这个简单的示例应用的必要的细节,这个应用是可下载的并且可以在你的环境中布署来看看DWR如何工作。
注意:找到有关AJAX的信息并不困难;网页上有几篇文章和博客的条目涵盖了这个主题,每一个都试图指出和评论这个概念的不同的方面。在资源部分,你会找到一些有趣的指向示例和文章的链接,来学习AJAX的更多的内容。

示例应用
这篇文章使用的示例应用模拟了多伦多的一个公寓出租搜索引擎。用户可以在搜索前选择一组搜索标准。为了提高交互性,AJAX中以下两种情况下使用:
·应用通告用户配合他的选择会返回多少搜索结果。这个数字是实时更新的-使用AJAX-当用户选择的卧室和浴室的数量,或者价格范围变化时。当符合标准的搜索结果没有或太多时,用户就没有必要点击搜索按纽。
·数据库查询并取回结果是由AJAX完成的。当用户按下显示结果按钮时,数据库执行搜索。这样,应用看起来更具响应了,而整个页面不需要重载来显示结果。

数据库
我们使用的数据库是HSQL,它是一种占用资源很小的Java SQL数据库引擎,可以不需要安装和配置的与Web应用捆绑在一起。一个SQL文件被用来在Web应用的上下文启动时创建一个内存中的表并添加一些记录。

Java类
应用包含了两个主要的类叫Apartment和ApartmentDAO。Apartment.java类是一个有着属性和getter/setter方法的简单的Java类。ApartmentDAO.java是数据访问类,用来查询数据库并基于用户的搜索标准来返回信息。ApartmentDAO类的实现的直接了当的;它直接使用了Java数据库联接调用来得到公寓的总数和符合用户请求的可用公寓的列表。

DWR配置和使用
设置DWR的使用是简单的:将DWR的jar文件拷入Web应用的WEB-INF/lib目录中,在web.xml中增加一个servlet声明,并创建DWR的配置文件。DWR的分发中需要使用一个单独的jar文件。你必须将DWR servlet加到应用的WEB-INF/web.xml中布署描述段中去。

								    <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上,它显示了对象的公共方法。所列方法可以从页面中调用,允许你,第一次,运行服务器上的对象的方法。下图显示了调试页的样子:

image
调试页

现在你必须让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/util

DWRUtil.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/lists

DWRUtil.addRows() 返回的集合来填充table元素,或者tbody更为合适 
 
posted on 2006-09-19 16:38 智者无疆 阅读(913) 评论(2)  编辑  收藏 所属分类: Client teachnolgy research
评论:
  • # re: dwr实例  zhanglijun Posted @ 2008-03-11 11:16
    1.jsp文件里:<script type='text/javascript' src='<c:url value="/dwr/interface/dwrUser.js"/>'></script>
    <script type='text/javascript' src='/dwr/interface/dwrCorps.js'/></script>
    <script type='text/javascript' src='<c:url value="/dwr/engine.js"/>'></script>
    <script type='text/javascript' src='<c:url value="/dwr/util.js"/>'></script>
    function findCorpsOnPage(pageNum){
    var pageSize =10;
    if(pageNum==0)pageNum=1;
    //alert("begin");

    dwrUser.getCorsOnPage2(pageSize,pageNum,callShowCorps2);
    }

    function callShowCorps2(data){
    var dd = document.getElementById('dd');
    document.getElementById("dd").innerHTML= pcont;
    var ddContent = dd.innerHTML;

    if(data!=null){
    var cons_name;
    var cons_id;
    for(var i=0;i<data.results.length;i++){
    var div="<div class=test style='width:200px;float:left; '>"+
    "<a href=\"javascript:checkIt(id1,'corpName')\">corpName</a></div>";
    cons_name = data.results[i].name;
    cons_id =data.results[i].id;
    div = div.replace(/corpName/g,cons_name);
    div = div.replace(/id1/,cons_id);
    ddContent += div;
    }
    ddContent+="<br/><br/><p/><hr/>"
    for (i=1;i<=data.totalPageCount;i++){

    var p= "<a href=\"javascript:findCorpsOnPage("+i+")\" >"+i+"</a> ";
    if(data.pageNum==i)
    p = "<a href=\"javascript:findCorpsOnPage("+i+")\" ><font color=red >"+i+"<font></a> ";


    ddContent+=p;


    }
    dd.innerHTML =ddContent;
    }else{

    alert("没有企业");
    }
    }



    2.与web.xml并行的dwr.xml
    <dwr>
    <allow>
    <convert converter="bean" match="cn.com.swjay.data.model.Corporation"></convert>
    <convert converter="bean" match="cn.com.swjay.data.model.impl.CorporationImpl"/>
    <convert converter="bean" match="cn.com.swjay.monitoring.service.model.CorporationService"/>
    <convert converter="bean" match="cn.com.swjay.monitoring.service.model.impl.CorporationServiceImpl.java"/>
    <convert converter="bean" match="cn.com.opendata.platform.common.page.Page"/>

    <create creator="new" javascript="dwrUser" scope="application">
    <param name="class" value="cn.com.swjay.monitoring.dwr.DwrController"/>
    </create>
    <create creator="new" javascript="dwrCorps">
    <param name="class" value="cn.com.swjay.guidelineconfig.dwr.Corperations" />
    </create>
    </allow>
    </dwr>
      回复  更多评论   

  • # re: dwr实例  zhanglijun Posted @ 2008-03-11 11:17
    @zhanglijun
    localhost:8080/项目名/dwr/
    这样可以进行dwr类的测试  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
 
Copyright © 智者无疆 Powered by: 博客园 模板提供:沪江博客


   观音菩萨赞