DWR 简介--转载
目前 Ajax 的开发框架有很多,使用这些框架可以简化 Ajax 的开发。DWR (Direct Web Remoting) 是一个用于改善 Web 页面与 Java 类交互的远程服务器端 Ajax 开源框架。DWR 可以动态生成基于 Java 类的 JavaScript 代码。对于公开的每个类,DWR 帮我们做好了创建对象、发送数据、接受响应等许多繁琐的工作,大大节省了客户端代码和工作量。
本文使用的示例应用程序是一个简单的用户注册过程。借助简化了的数据模型,主要介绍 DWR 和 Spring MVC 的结合。我们先来研究一下 DWR 如何启用程序的 Ajax 功能。
首先,需要下载 dwr.jar 文件,把它放在 web 程序的 WEB-INF/lib 目录下面。清单 1 显示了要公开给 Ajax 的 Java 方法。
清单 1. 需要公开的 userManager 类的两个方法
public int findExistedUser(String name) public List<User> showUsers() |
接下来需要配置 DWR,告诉它 Ajax 应当如何构建 userManager 并调用这些方法。在清单 2 所示的 dwr.xml 文件中进行配置。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd"> <dwr> <allow> <create creator="spring" javascript="userManager" scope="application"> <param name="beanName" value="userManager"/> <include method="findExistedUser"/> <include method="showAllUsers"/> </create> <convert converter="bean" match="com.ibm.osl.entity.User"> <param name="include" value="name"/> </convert> </allow> </dwr> |
creator 属性用来指定使用哪种创造器。如果 creator 属性被设置为值 new,意味着 DWR 调用类的默认构造函数来获得实例。这里通过与 Spring 进行集成来获得实例,creator="spring" 提供了一个 Spring 的创造器,允许直接调用 Spring 容器中的 bean,然后 DWR 将 bean 转换成一个 javascript 对象。SpringCreator 这个创造器会查找 Spring 所配置的 bean,并创建它们。Javascript 属性用于指定浏览器中被创造出来的对象的名字。scope 属性指定这个 bean 的生命周期。嵌套在 create 元素内的 param 元素的 name 属性值可以是 class,beanName 等。此处用 beanName,value 的值 userManager 是在 beans.xml 中定义的某个 id 值。include 元素指定公开的方法名称。也可以用 exclude 元素指定不想被被访问的方法。
convert 元素的作用是告诉 DWR 在服务器端的 Java 对象表示和 JavaScript 之间如何转换数据类型。
DWR 能自动地在 Java 对象和 JavaScript 表示之间转换简单数据类型。这些类型包括 Java 原生类型和它们各自的类表示,还有数组和集合类型。这里 convert 元素告诉 DWR 用 bean 转换器处理 showAllUsers 方法返回的 List<User> 对象,并指定序列化中只包含 User 类 的 name 属性。
接下来在清单 3 中定义需要的 bean 。
<beans> <bean id="userManager" class="developworks.dwrspring.service.impl.UserManagerImpl"/> </beans> |
有三种方式寻找配置文件 beans.xml,最简单的方式是使用 org.springframework.web.context.ContextLoaderListener。需要在 web.xml 中做如下配置:
清单 4. 使用 ContextLoaderListener 寻找配置文件 beans.xml
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/beans.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> |
如果在 web.xml 中把 init-param 的 debug 属性设置为 true,就会启用 DWR 的测试模式,如清单 5 所示。访问 /[web-app]/dwr/ 就可以看到服务器暴露出来的所有类列表。
清单 5. 将 web.xml 的 debug 属性设置为 true
<init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> |
Classes known to DWR: * userManager (developworks.dwrspring.service.impl.UserManagerImpl) |
点击进入 userManager 可以看到该类暴露出的所有方法,并可以进行测试。这里有两个用户自己定义的方法,可以在可访问的方法旁边的文本框中输入参数值并点击 Execute 按钮调用方法。服务器的响应如果是简单值,会在方法旁边直接显示。其他的输出将在警告框中用 JSON 标注显示出来。这样,测试页面不仅可以检查公开了哪个类和方法用于远程调用,还可以测试每个方法是否正常工作。下面让我们看下本例中的两个方法:
函数 findExistedUser("") 可以查找是否存在该用户。若不输入参数,点击 Execute 按钮,显示 0。在函数参数中输入已存在的 id,如 "tom@cn.ibm.com",点击 Execute 按钮,显示 1。
函数 showAllUsers() 可以显示所有的用户名。点击 Execute 按钮,会弹出一个显示所有 user 信息的警告框,内容如清单 7。
清单 7. 点击 Execute 按钮返回的 JSON 对象
[ {name:"tom@cn.ibm.com"}, {name:"mike@cn.ibm.com"} ] |
对于公开的每个类,DWR 动态地生成包含在 Web 页面中的 JavaScript。生成的 JavaScript 包含存根函数,代表 Java 类对应的方法。Java 方法与对应的 JavaScript 函数之间的映射规则为 JavaScriptName.methodName(methodParams ..., callBack),其中 JavaScriptName 是 creator 属性指定浏览器中被创造出来的对象名字,methodName 是 Java 的方法名,methodParams 代表 Java 方法的参数,最后的 callBack 是 Java 方法返回后要回调的 JavaScript 函数。清单 8 是在 jsp 页面中使用 DWR 创建的 javascript 对象调用公开的方法。
function callBackfindExistedUser(data){ var userExistedMessage = $("userExistedMessage"); if (data == 1) userExistedMessage.style.display = "block"; else userExistedMessage.style.display = "none"; } function findExistedUser(){ var name = DWRUtil.getValue("name"); if (name != "") userManager.findExistedUser(name,callBackfindExistedUser); } |
在 jsp 页面使用 DWR,需要添加清单 9 的代码。
<script type='text/javascript' src='dwr/interface/userManager.js'></script> <script type='text/javascript' src='dwr/engine.js'></script> <script type='text/javascript' src='dwr/util.js'></script> |
DWR 会自动根据 UserManager 类帮我们生成了 userManager.js 文件。engine.js 是用来转换动态生成接口的 javascript 函数调用,util.js 包含了一些工具函数,让页面对 javascript 的调用更加方便。