`

在 Spring Web MVC 环境下使用 DWR

 
阅读更多

DWR 简介

目前 Ajax 的开发框架有很多,使用这些框架可以简化 Ajax 的开发。DWR (Direct Web Remoting) 是一个用于改善 Web 页面与 Java 类交互的远程服务器端 Ajax 开源框架。DWR 可以动态生成基于 Java 类的 JavaScript 代码。对于公开的每个类,DWR 帮我们做好了创建对象、发送数据、接受响应等许多繁琐的工作,大大节省了客户端代码和工作量。

示例应用程序:用户注册

本文使用的示例应用程序是一个简单的用户注册过程。借助简化了的数据模型,主要介绍 DWR 和 Spring MVC 的结合。我们先来研究一下 DWR 如何启用程序的 Ajax 功能。

配置 DWR

首先,需要下载 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 文件中进行配置。


清单 2. 配置 DWR,公开需要远程调用的方法

				
 <?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 。


清单 3. 配置 beans.xml

				
 <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> 



清单 6. 服务器端暴露出来的所有类列表

				
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 对象调用公开的方法。


清单 8. 用 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 的代码。


清单 9. 在 jsp 页面使用 DWR 要包含的文件

				
 <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 的调用更加方便。

 

Spring MVC 简介

Spring 框架提供了构建 Web 应用程序的 MVC 模块。Spring MVC 内建了一个请求驱动的 web mvc 框架,以一个 DispatcherServlet 分发器为中心,将 web 请求分发到各个不同的处理器进行处理。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色。

配置 Spring MVC

需要下载 spring.jar 和 spring-webmvc.jar 包,将它放在 web 程序的 WEB-INF/lib 目录下面。

本例中使用控制器 AbstractWizardFormController,它的主要功能是允许多个表单共用一个表单对象,通常一些表单填的内容比较多,表单会很长,可以将表单分成几页,让用户一页页去完成。表单对象的属性与多个页面所有需填写的对象绑定。AbstractWizardFormController 类的 processFinish 方法定义的是全部表单完成后提交的处理。所有的表单内容都收集在 command 对象中,通过 ModelAndView 的构造方法把它放在 model 对象中,并在 view 页面上显示出来。


清单 10. processFinish 方法将表单内容传输给 view 页面

				
 protected ModelAndView processFinish(HttpServletRequest request, 
 HttpServletResponse response, 
 Object command, 
 BindException exception) throws Exception { 
 RegisterForm registerForm = (RegisterForm) command; 
 return new ModelAndView(this.getSuccessView(), "registerForm", registerForm); 
 } 

 

清单 11 在 mvc-config.xml 中对 controller 进行配置。


清单 11. 对 controller 进行配置

				
 <bean id="registerController" class=" developworks.dwrspring.action.RegisterController"> 
    <property name="commandClass" value="developworks.dwrspring.vo.RegisterForm"> 
 </property> 
 <property name="userManager" ref="userManager"></property> 
 <property name="successView" value="account/success"/> 
 <property name="pages"> 
 <list> 
 <value>account/register1</value> 
 <value>account/register2</value> 
 </list> 
 </property> 
 </bean> 

 

这里 commandClass 用来绑定 form 的 bean class。list 元素定义的两个 value 值分别表示表单的第一个页面和第二个页面。successView 属性表示表单提交后要转到的页面。

第一个页面中的表单内容如下:


清单 12. 第一个表单页面

				
 <form:form action="register.action" method="post"> 
 <form:input path="name" onblur="javascript:findExistedUser()"/> 
 <form:input path="age"/> 
 <input type="submit" value="Next" name="_target1" /> 
 </form:form> 

 

path 中的属性 name 对应的是表单对象 RegisterForm 的 name 属性。Javascript 方法 findExistedUser 会调用 DWR 产生的 javascript 对象的 findExistedUser 方法来判断是否存在该用户。

_target1 的数字 1 表示在 xml 文件中 <list> 的顺序。这里 _target1 对应的是 account/register2 页面。即提交后转到第二个表单页面继续填写。

第二个页面中的表单内容如下:


清单 13. 第二个表单页面

				
 <form:form action="register.action" method="post"> 
 <form:select path="location"> 
 <form:option value="" label="---"/> 
 <form:options items="${location}"/> 
 </form:select> 
 <input class="button" type="submit" value="Back" name="_target0"/> 
 <input class="button" type="submit" value="Submit" name="_finish" /> 
 </form:form> 

 

_target0 对应的是 account/register1 页面。即回到前一个表单页面。

_finish 会执行 controller 的 processFinish 方法。

path 中的属性 location 所含的数据来自于 controller 的 referenceData 函数为表单页面准备的数据。


清单 14. 为页面的 select 框准备数据

				
 protected Map<String,Object> referenceData(HttpServletRequest request, int page) 
     throws Exception { 
 refData = new HashMap<String,Object>(); 
 if (page == 1){ 
 Map<String,Object> location = new HashMap<String,Object>(); 
 location.put("0", "Beijing"); 
 location.put("1", "Shanghai"); 
 refData.put("location", location); 
 } 
 return refData; 
 } 

 

referenceData 函数为第二个页面 register2.jsp 的 select 框的 location 下拉框添加选项。

最后在 success 页面通过 <c:out value="${registerForm.name}" /> 等 jstl 标签显示先前表单输入的值。用户还可以通过点击按钮 showAllUsers 来显示当前所有用户。因为在 convert 属性中只配置了 name 属性,所以用户只能看到所有的用户名。若输出 age 属性,显示 undefined。


清单 15. 在页面中显示所有的用户名

				
 function showAllUser(){ 
    userManager.showUsers(callBackAllUser); 
 } 
 function callBackAllUser(data){ 
    var result = ""; 
    for (var i = 0; i < data.length; i++){ 
        result += data[i].name + ", "; 
    } 
    DWRUtil.setValue("demoAllUser",result); 
 } 

 

 

使用 DWR 标注

DWR 从 2.0 版本开始支持标注,需要在 JDK1.5 以上使用。使用标注可以省掉 dwr.xml,把这个文件的配置信息都移植到程序代码中。下面看一下配置过程。首先,需要在 web.xml 中配置,把使用 DWR 注释的类都要加在这里。


清单 16. 对 web.xml 进行配置

				
 <init-param> 
    <param-name>classes</param-name> 
    <param-value> 
        com.ibm.osl.service.impl.UserManagerImpl, 
        com.ibm.osl.entity.User, 
    </param-value> 
 </init-param> 

 

接下来对要远程调用的方法进行标注。


清单 17. 配置要远程调用的方法

				
 @RemoteProxy(name="userManager",creator=SpringCreator.class, 
 creatorParams={@Param(name="beanName",value="userManager"),}) 
 public class UserManagerImpl implements UserManager { 
    @RemoteMethod 
    public int findExistedUser(String name){ 
 return accountDAO.findExistedUser(String name); 
    } 
    @RemoteMethod 
    public List<User> showUsers(){ 
 return accountDAO.showUsers(); 
    } 
 } 

 

@RemoteProxy 标注要远程调用的类,也就是告诉 DWR,这个 class 是要暴露出来的。相当于 dwr.xml 中的 <creator> 标签。RemoteProxy 的 name 指定暴露出来的 DWR 接口的名字,creator 指定使用哪种创造器,本例中使用 SpringCreator。creatorParams 指定创造器的其他参数。

@RemoteMethod 标注要远程调用的方法。只有加了 @RemoteMethod 标注的方法才会被暴露。

接下来对 bean 的转换进行配置。


清单 18. 配置要转换的 bean

				
 @DataTransferObject(converter=BeanConverter.class) 
 public class User { 
    private String name; 
    private Integer age; 
    public String getName() { 
        return name; 
    } 

    @RemoteProperty 
    public void setName(String name) { 
        this.name = name; 
    } 

    public Integer getAge() { 
        return age; 
    } 

    public void setAge(Integer age) { 
        this.age = age; 
    } 
 } 

 

@DataTransferObject 标注在客户端和服务器之间转换类。相当于 dwr.xml 中的 <convert> 标签。@RemoteProperty 标注在类中需要转换的属性。这里只对 name 进行标注。进行以上配置后,就可以达到和使用 dwr 的 xml 配置文件一样的效果了。

 

DWR 的安全性

在使用 DWR 时要明确哪些类和方法是可以被远程调用的。dwr.xml 要求为每一个远程类定义一个 create 项。还可以通过指定 include 和 exclude 元素控制远程调用 Bean 中可以被调用的方法,而不是把所有的方法都暴露给服务器端。除此之外,如果要 DWR 在转换 JavaBean 到 Javascript 时有一定限制,可以控制哪些 bean 的属性可以被转换。特别地,在做删除和更新操作时,可以通过 WebContext 得到 session 来判断用户是否有权限进行该操作。另外,不要在生产环境中打开 debug 属性。

 

结束语

DWR 为在客户端使用服务器端的对象和方法提供了一条捷径,并且 DWR 还提供了一个 Spring 的创建器,允许直接调用 Spring 容器中的 bean,将 bean 转换成一个 javascript 对象。通过本文,您了解了如何结合使用 DWR 和 Spring MVC。

 

参考资料

学习

讨论

关于作者

高乐怡,目前是 IBM 中国系统与科技中心的软件工程师,从事测试工具的开发工作。

分享到:
评论

相关推荐

    spring mvc 自动注入+dwr

    总结,Spring MVC 的自动注入简化了对象之间的依赖关系管理,而 DWR 提供了与服务器交互的能力,两者结合可以在不刷新页面的情况下实现动态数据更新,提升用户体验。在实际开发中,理解并熟练运用这些技术能有效提高...

    spring mvc+dwr环境配置

    在本篇配置手册中,我们将介绍如何在Spring MVC的环境下配置DWR环境,这包括web.xml的配置、创建dwr.xml文件、添加DWR的jar包、形成推送函数类以及在前台页面引入对应的JavaScript文件。 首先,web.xml的配置是整个...

    Spring mvc +mybatis +dwr 整合

    Spring MVC、MyBatis和Direct Web Remoting (DWR) 是三个常见的Java框架,它们分别处理MVC(Model-View-Controller)架构、数据库持久化和Web服务交互。本文将深入探讨如何将这三个框架整合起来,以及JNDI(Java ...

    spring mvc+ibatis+dwr实现dispatchservlet

    Spring MVC、iBATIS(现在称为MyBatis)和Direct Web Remoting (DWR) 是三个常用的Java框架,它们各自在不同的层面上发挥着作用,共同为开发高质量的Web应用提供支持。本文将深入探讨如何使用这些技术实现...

    DWR整合Spring MVC

    **DWR整合Spring MVC**是将Direct Web Remoting (DWR)框架与Spring MVC结合使用,以实现前端JSP页面直接调用后端Java方法的功能。这种整合方式极大地提高了Web应用的交互性和实时性,降低了数据传输的复杂性。本文将...

    spring3mvc+hibernate4+spring-security3+dwr3整合架包

    本篇文章将深入探讨“spring3mvc+hibernate4+spring-security3+dwr3整合架包”中的核心技术和概念,帮助开发者理解如何利用这些组件来创建强大的Java Web应用。 首先,Spring MVC(Model-View-Controller)是Spring...

    将dwr集成到spring mvc(dwr的配置是基于xml)

    在Spring MVC框架中集成DWR,可以进一步提升用户体验,因为Spring MVC专注于处理控制器逻辑,而DWR则负责客户端与服务器之间的通信。 集成DWR到Spring MVC的过程主要包括以下几个步骤: 1. **引入依赖**:首先,你...

    maven与spring MVC

    综上所述,这个项目可能是一个使用Maven构建的Java Web应用,采用Spring MVC作为MVC架构,利用Hibernate进行数据库操作,通过Validation进行数据验证,并且使用DWR来增强前端的交互性。这样的组合提供了一个强大、...

    spring+dwr.rar_dwr_dwr SPRING_spring dwr

    在IT领域,Spring框架和Direct Web Remoting (DWR)是两种重要的技术,它们在构建分布式Web应用程序中发挥着关键作用。本篇文章将详细讲解如何利用Spring与DWR结合,实现一个基本的功能:判断用户名是否已经存在于...

    spring mvc jpa cxf dwr jar包合集

    Spring MVC、JPA、CXF和DWR是Java开发中常用的四大框架或库,它们各自在不同的领域提供了强大的功能,并且在企业级应用开发中扮演着重要的角色。下面将详细介绍这些技术及其相互间的关联。 **Spring MVC** Spring ...

    DWR与SPRING 集成

    标题 "DWR与SPRING 集成" 涉及到的是两个在Web开发中常用的开源框架——Direct Web Remoting (DWR) 和 Spring。DWR允许在浏览器和服务器之间进行实时、异步的数据交换,而Spring是Java企业级应用的全面解决方案,...

    dwr+spring实例

    要将DWR与Spring整合,我们通常会使用Spring的`DwrController`或者自定义一个Spring MVC控制器来处理DWR请求。此外,我们还需要在Spring的配置文件中声明DWR的相关bean,如`DwrConfig`,并将其与其他Spring服务(如...

    Spring+Dwr整合的项目(源码)

    通过这个项目,开发者可以深入理解Spring和DWR的整合机制,提升在Web开发中的实战能力,尤其是对于需要实时交互的应用场景,DWR的使用能极大地提升用户体验。同时,注解方式的整合也展示了现代化开发的趋势,即简化...

    在Spring中使用dwr

    &lt;artifactId&gt;spring-webmvc &lt;version&gt;5.3.16 &lt;!-- DWR 相关依赖 --&gt; &lt;groupId&gt;com.getahead&lt;/groupId&gt; &lt;artifactId&gt;dwr &lt;version&gt;3.0.2 ``` #### 三、配置DWR 1. **在`web.xml`中配置DWR** 在项目...

    dwr+spring 注解方式

    在使用DWR和Spring结合时,注解方式的引入极大地简化了配置过程。下面将详细介绍如何通过注解实现DWR和Spring的集成以及相关知识点: 1. **Spring注解配置**: - `@Configuration`:标记一个类为Spring配置类,可...

    DWR与SPRING,DWR与STRUTS2的整合

    综上所述,"DWR与SPRING,DWR与STRUTS2的整合"主题涵盖了现代Java Web开发中重要的三个方面:DWR的实时通信能力、Spring的全面后端支持和Struts2的MVC架构。通过整合这三者,开发者可以构建出具有高效交互、灵活管理...

    MyBatis升级版Dwr+Spring

    总之,Dwr+Spring的整合能够为Web应用带来高效、动态的数据交互,无论是在MVC框架内还是独立使用,都能提高开发效率和应用性能。通过学习和实践这两种整合方式,开发者可以更好地选择适合项目需求的技术栈。

    Spring DWR配置实例

    Spring Direct Web Remoting (DWR) 是一个Java库,它允许Web应用程序轻松地在客户端JavaScript和服务器端Java之间进行交互。这个技术的核心功能是提供了一种机制,使得动态的、实时的Web应用成为可能,无需刷新整个...

    DWR2.0 整合Spring2.0

    4. 在Spring MVC的配置中添加DWR的Servlet映射。 5. 在JavaScript中使用DWR提供的API调用服务器端的方法。 通过以上整合,开发者可以充分利用DWR的实时通信能力,同时享受到Spring框架带来的便利和灵活性,提高开发...

Global site tag (gtag.js) - Google Analytics