转载自:http://wtnhwbb.iteye.com/blog/107687
概述
以前在公司用Confluence记录一些整理的文档,现在移交到JAVA EYE,下面的文档还是基于DWR1.0版本的。
DWR是一个AJAX开源库,允许浏览器端调用服务器端的JAVA函数,就好像这些函数是在浏览器端。DWR包含两个主要的部分:
- 一个JAVA SERVLET运行在服务器端,处理请求并发送响应给客户。
- JavaScript运行在浏览器端,发送请求并动态更新网页。
DWR通过基于JAVA类动态的生成javascript脚本来实现,这些代码在后台做一些AJAX操作,实际上是服务器在执行代码,DWR来回执 行数据序列化和反序列化。调用的是javascript代码,而实际上执行的是Java代码,使用户感觉好像是使用传统的RPC机制,如RMI或者 SOAP,而其优点是不需要在浏览器端安装插件。
Java基本上是同步的,而Ajax是异步的。因此当你调用远程方法时,你需要提供DWR一个回调函数,这样当数据从服务器端返回时,DWR会调用这个回调函数更新页面或做一些其他的操作
DWR可以动态的生成一个Javascript的AjaxService类对应服务器端的AjaxService类。这个方法被eventHandler调用,DWR负责处理所有的远程交互细节,包括在JAVA和Javascript之间转换所有的参数和返回值。然后执行提供的回调函数(这里是populateList(data))。
快速上手
添加库文件
从http://getahead.ltd.uk/dwr/download下载dwr.jar,拷贝到你的WEB应用程序的 WEB-INF/lib目录下
更改配置
需要更改WEB.XML文件的配置,添加对DWR SERVLET的配置,类似如下:
xml 代码
<servlet>
<servlet-name>dwr-invokerservlet-name>
<display-name>DWR Servletdisplay-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServletservlet-class>
<init-param>
<param-name>debugparam-name>
<param-value>trueparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>dwr-invokerservlet-name>
<url-pattern>/dwr/*url-pattern>
servlet-mapping>
然后需要WEB-INF目录下创建dwr.xml文件,一个最简单的示例文件如下:
xml 代码
- <dwr>
- <allow>
- <create creator="new" javascript="JDate">
- <param name="class" value="java.util.Date"/>
- create>
- <create creator="new" javascript="Demo">
- <param name="class" value="your.java.Bean"/>
- create>
- allow>
- dwr>
DWR配置文件定义DWR能将哪些JAVA类转换成JAVASCRIPT类,上述例子中DWR可以创建两个类,create元素的javascript属性用来定义相应的JAVA类在javascript中的名称。
new creator要求所有的javabean类必须有一个无参数的构造函数,另外DWR还有一些限制如下:
- 避免使用Javascript预留关键字,使用保留关键字的方法都会被自动排除,大部分javascript保留关键字也是java保留关键字,因此不可以有一个方法命名为try。
- 另外要避免使用重载方法。
测试配置
发布WEB应用程序,然后在浏览器输入如地址http://localhost:8080/YOUR-WEBAPP/dwr/,这里的YOUR-WEBAPP是指应用程序的名字。这时候你应该可以看到你上一步发布的两个类的链接,进一步可以看到所有暴露的方法索引。
客户端调用
客户端页面中需要添加对相应脚本的引用,类似如下:
xml 代码
<script src='/YOUR-WEBAPP/dwr/interface/[TEC:YOUR-SCRIPT].js'>script>
<script src='/YOUR-WEBAPP/dwr/engine.js'>script>
也可以忽略[YOUR-WEBAPP使用相对路径。
配置dwr.xml文件
dwr.xml 是DWR必须的配置文件,缺省需要放置在WEB-INF目录下。如下是一个dwr.xml文件结构示例:
xml 代码
- "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
- "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
-
- <dwr>
-
-
- <init>
- <creator id="..." class="..."/>
- <converter id="..." class="..."/>
- init>
-
-
- <allow>
- <create creator="..." javascript="..."/>
- <convert converter="..." match="..."/>
- allow>
-
-
- <signatures>
- ...
- signatures>
-
- dwr>
术语
有一些术语需要了解,参数被converted,但是远程bean实例被created。因此如果你有一个类A,有一个方法A.blah(B),那么你需要一个类A的creator和一个B的转换器。
<allow></allow>
allow元素用来定义DWR可以创建和转换哪些类型。
Creators
每个我们需要调用其方法的类,必须有一个<create></create>入口。有几种类型的creator,最常用的是使用new关键字定义的creator或者使用spring框架提供的creator。详情请参见http://getahead.ltd.uk/dwr/server/dwrxml/creators。
Converters
必须保证所有的参数都可以转换。DWR支持许多JDK缺省提供的类型,但是如果是自定义的类型,通常需要在配置文件中添加一个<converter></converter>入口。
缺省情况下,下列类型转换不需要额外的声明:
- 所有的原始类型及其包装类
- String,java.util.date和其三个SQL子类。
- 上述类型的数组。
- 上述类型的集合(List,Set,Map,Iterator)。
- DOM对象,如来自于DOM, XOM, JDOM和DOM4J的Element和Document类型
如何定义自定义的转换器来转换自己BEAN,请参见相关文档http://getahead.ltd.uk/dwr/server/dwrxml/converters。
<init></init>
这个区域用来定义那些Creator和Convertor实例。大部分情况下你不需要使用这个元素。如果你需要定义一个新的Creator或者Convertor类型时,才需要在这里添加声明。
这个区域有一个入口仅仅告诉DWR这些类的存在,以及提供使这些类工作的详细信息,这有点类似于JAVA的import语句,大多数类在使用前必须导入,但是导入了不表示这些类就会被用到。每个Creator和Convertor都有一个ID属性,允许随后被引用。
多个dwr.xml文件
一般来说,你只需要一个dwr.xml文件,并且放置在默认的位置:WEB-INF/dwr.xml。 如果那样的话,你可以不用了解下面的配置。
有三个原因使你希望指定不同位置的dwr.xml文件。
- 你希望让dwr.xml文件和它能访问到的资源在一起。在这种情况下你需要一个这样的配置: <param-value></param-value> WEB-INF/classes/com/yourco/dwr/dwr.xml 。
- 你有大量的远程调用类,希望把他们分成多个文件。在这种情况下你需要重复下面的配置几次,每一个中有不同的 param-name,并且以 'config' 开头。DWR会依次把他们都读进来。
- DWR可以使用Servlet规范的J2EE的URL安全机制来给不同的用户不同的访问权限。你只需要简单的定义多个dwr servlet,并且制定不同的名字,url和访问权限。
如果你希望使用这一功能,那么语法是这样的:
init-param>
param-name>config*****</param-name>
param-value>WEB-INF/dwr.xml</param-value>
description>What config file do we use?</description>
/init-param>
在这里config*****意思是param-name要以字符串'config'开头。这个参数可以根据需要使用多次,但是不能相同。
一个使用J2EE的安全机制的例子:
<servlet></servlet>
<servlet></servlet> servlet>
servlet-name>dwr-user-invoker</servlet-name>
servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
init-param>
param-name>config-user</param-name>
param-value>WEB-INF/dwr-user.xml</param-value>
/init-param>
/servlet>
servlet>
servlet-name>dwr-admin-invoker</servlet-name>
servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
init-param>
param-name>config-admin</param-name>
param-value>WEB-INF/dwr-admin.xml</param-value>
/init-param>
/servlet>
servlet-mapping>
servlet-name>dwr-admin-invoker</servlet-name>
url-pattern>/dwradmin/*</url-pattern>
/servlet-mapping>
servlet-mapping>
servlet-name>dwr-user-invoker</servlet-name>
url-pattern>/dwruser/*</url-pattern>
/servlet-mapping>
security-constraint>
display-name>dwr-admin</display-name>
web-resource-collection>
web-resource-name>dwr-admin-collection</web-resource-name>
url-pattern>/dwradmin/*</url-pattern>
/web-resource-collection>
auth-constraint>
role-name>admin</role-name>
/auth-constraint>
/security-constraint>
security-constraint>
display-name>dwr-user</display-name>
web-resource-collection>
web-resource-name>dwr-user-collection</web-resource-name>
url-pattern>/dwruser/*</url-pattern>
/web-resource-collection>
auth-constraint>
role-name>user</role-name>
/auth-constraint>
/security-constraint>
工具方法
util.js包含许多工具方法,你可以独立于DWR使用这些函数。
创建列表
DWR通常需要填充一个列表框,主要是addOptions和removeAllOptions方法。如果当你更新时需要维护列表,通常需要如下代码:
var sel = DWRUtil.getValue(id);
DWRUtil.removeAllOptions(id);
DWRUtil.addOptions(id, ...);
DWRUtil.setValue(id, sel);
DWRUtil.addOptions(selectid,array)
数组的每一个元素的字符串表示值和文本,值和文本属性是一样的。
DWRUtil.addOptions( "demo1", ['Africa', 'America', 'Asia', 'Australasia', 'Europe' ])
DWRUtil.addOptions(selectid, data, prop)
数组的每一个元素是一个对象,prop表示值和文本对应的属性名称,这里值和文本属性是一样的。
DWRUtil.addOptions( "demo1",[
{ name:'Africa', population:'800m' },
{ name:'America', population:'900m' },
{ name:'Asia', population:'3000m' },
{ name:'Australasia', population:'31m' },
{ name:'Europe', population:'700m' }
],"name")
DWRUtil.addOptions(selectid, array, valueprop, textprop)
数组的每一个元素是一个对象,其valueprop和textprop属性表示值和文本对应的属性名称。
DWRUtil.addOptions( "demo1",[
{ name:'Africa', id:'AF' },
{ name:'America', id:'AM' },
{ name:'Asia', id:'AS' },
{ name:'Australasia', id:'AU' },
{ name:'Europe', id:'EU' }
],"id","name")
DWRUtil.addOptions(selectid, map, reverse)
MAP的每一个属性键表示属性值,属性值表示文本,如果reverse属性为true,那么属性键表示文本,属性值表示值。
DWRUtil.addOptions( "demo1",{
AF:'Africa',
AM:'America',
AS:'Asia',
AU:'Australasia',
EU:'Europe'
})
DWRUtil.addOptions(selectid, map, valueprop, textprop)
Map中的一个对象表示一个入口,其valueprop和textprop属性表示值和文本对应的属性名称。
DWRUtil.addOptions(ulid, array)
第一个参数表示一个ul或者ol元素的ID,每一个数组元素表示一个选项,其字符串表示会作为一个li元素的值。
创建表格
DWRUtil.removeAllRows()
接受一个ID参数,用来唯一标识需要删除的表格元素。
DWRUtil.addRows()
语法
DWRUtil.addRows(id, array, cellfuncs,options);
描述
添加数据到指定的表格元素。从一个数组中接受数据,数组的每一个元素表示表格中的一行,cellfuncs数组中的一个元素表示一列。单元格通过针对每一个数据数组循环调用cellfuncs的函数生成。
处理伪代码类似如下:
for each member in array
for each function in cellfuncs
create cell from cellfunc(array[i])
参数
- id: 表格元素ID值
- array: 数组或者是对象,一个元素表示表格中的一行。
- cellfuncs: 表示函数的数组,每一个元素表示一个函数,用来从提供的行数组中解析数据。
- options: 一个包含不同选项的对象。
目前可用的选项是:
- rowCreator: 用来创建一行的函数(比如你想给TR标记添加CSS)。缺省返回document.createElement("tr") 。
- cellCreator: 用来创建一个单元格的函数(比如用一个TH代替TD)。缺省返回document.createElement("td") 。
获值/设置方法
DWRUtil.getValue(id)是setValue()对应的获值方法。用来获取指定元素的值,而不必关心给定元素是一个DIV还是一个下拉列表。
getValues()类似于getValue()方法,区别是其参数是一个包含键值对的javascript对象。名字是需要从中获取值的元素的ID, 值将被改变用来反应相应元素的值。这个方法不返回值,而是改变传递进去的对象的值,这个方法用来一次获取多个元素的值,示例代码如下:
DWRUtil.getValues({ div:null, textarea:null, select:null, text:null, password:null, formbutton:null, button:null })
getText(id)类似于getValue,区别是它主要是针对select元素用来获取显示的文本而不是当前显示的值。
$()
这个函数来源于Protoype库,简单地讲$ = document.getElementById,因为在AJAX中后者经常被使用。
这个函数用来从当前Document中获取指定ID的元素,也可以一次获取多个元素的数据。
DWRUtil.toDescriptiveString
这个方法主要用来调试,第一个参数是需要输出的对象,第二个参数是需要输入的信息详细程序,有三个选项:
- 0: 一行信息
- 1: 多行调试信息,不包含子对象的信息
- 2: 多行调试信息,包含当前对象的第二层次的子对象的信息