`
寻找出路的苍蝇
  • 浏览: 33912 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

DWR应用初探

阅读更多

    因工作需要,最近对DWR进行了探索性使用。在使用之前DWR的大名早就如雷贯耳了,但也只是仅闻其名而已,当时只知道它可通过JS直接调用JAVA对象方法,其它就一概不知了。实际应用DWR一段时后,对其了解比较深入,不禁被其优异的异步传输特性所折服,它能完全满足我在项目中应用AJAX的需求。

    GBP是我们的框架名称,它基于SSH,提供代码生成、基础组件调用等平台功能。在我们框架中引入DWR后,DWR代替struts充当控制层,用于接收用户请求,调用后台逻辑进行处理,最后将处理数据返回客户端。DWR全程处理从客户端到服务器端的所有传输细节。

下面是我在框架中使用DWR的一个初步总结,公布出来与大家共享。其中有很多内容是从网上查找资料学习到的,有些地方甚至是直接引用原文。

DWR 是什么

     DWR 是一个可以允许你去创建 AJAX WEB 站点的 JAVA 开源库,它可以通过浏览器端的 Javascript 代码去调用服务器端的 Java 代码,看起来就像是 Java 代码运行在浏览器上一样。 DWR 是一个完整的异步 AJAX 框架,它隐藏了 XMLHttpRequest 对象,程序员在开发过程中不需要接触 XMLHttpRequest 对象就可以向服务器发送异步请求并通过回调方式处理服务器的返回值。

    DWR 包含两个主要部分:

  •   运行在服务器端的 servlet 控制器 (DwrServlet) ,它负责接收请求,调用相应业务逻辑进行处理,向客户端返回响应。

 

  •   运行在浏览器端的 Javascript ,它负责向服务器端发送请求,接收响应,动态更新页面。

 

    DWR 工作原理是通过动态把 Java 类生成为 Javascript 。它的代码就像 Ajax 魔法一样,你感觉调用就像发生在浏览器端,但是实际上代码调用发生在服务器端, DWR 负责数据的传递和转换。这种从 JavaScript Java 的远程调用功能的方式使 DWR 用起来有种非常像 RMI 或者 SOAP 的常规 RPC 机制,而且 DWR 的优点在于不需要任何的网页浏览器插件就能运行在网页上。

    Java 从根本上讲是同步机制,然而 Ajax 却是异步的。所以你调用远程方法时,当数据已从网络上返回的时候,你要提供有回调 (callback) 来接收数据。

 

    DWR 动态在浏览器端生成一个 AjaxService JavaScript 类,以匹配服务器端 AjaxService Java 类。由 eventHandler 去调用它,然后 DWR 处理所有的远程细节,包括转换所有的参数以及将返回的 Java 对象映射成 Javascript 对象。在示例中,先在 eventHandler 方法里调用 AjaxService getOptions() 方法,然后通过回调 (callback) 方法 populateList(data) 得到返回的数据,其中 data 就是 String[]{"1", "2", "3"} ,最后再使用 DWR utility data 加入到下拉列表。

 

为什么使用 DWR

    GBP 是建立在 Struts+Spring+Hibernate 之上的 MVC 框架,它的控制层是由 Struts 负责的,而视图层则是通过 JSP 页面呈现。

   

    由上可知,当前台页面向服务器发送一个请求时, struts 调用业务逻辑处理该请求获得处理数据,然后导航到配置的页面上显示结果数据。由此可见, struts 处理请求后一般是跳转到新的页面,浏览器需要进行页面刷新。这与目前流行的通过异步 AJAX 局部刷新页面的方式相比,界面的用户体验显然要差很多。当然 struts 也能实现 AJAX 异步调用,但目前 GBP 系统中对 AJAX 的使用方式比较原始零碎,没有一套完整成熟的规范来约束。而在 GBP 中引入 DWR 的直接目的正是为了正确使用 AJAX ,为 AJAX 异步调用建立一套规范。

    在 GBP 架构中可以用 DWR 来代替 Struts 做为控制器,用户请求通过 DWR 进行处理并发送响应。

    异步调用过程中, DWR 通过 JSP 页面上的 JS 代码可以直接调用业务处理逻辑的 Java 代码,这个调用过程看起来如下图所示:

 

    使用 DWR 时通过在浏览器端调用 JS 对象的方法就可以触发服务器 JAVA 对象的相应方法,并且自动完成 JS 对象与 JAVA 对象之间的数据类型转换,看起来就像是 Java 代码直接在浏览器上执行一样。其实在 JS 对象并不是直接操作 JAVA 对象的,这之间有一个控制器层, JS 方法调用时将请求发送到 DWR 控制器 DwrServlet ,然后通过 DwrServlet 调用相应的 JAVA 对象。完整的调用过程如下所示:

 

    与 Struts 相比, DwrServlet 接收到模型返回的处理数据后并不是导航到一个新的页面,而是将这些 JAVA 对象数据转化为 JS 对象数据然后发送到调用页面上,在页面上可以通过 JS 操纵 CSS DOM 等方式来局部更新页面。由此可见, DWR 通过异步 AJAX 方式的实现了页面的局部刷新效果,可以取得非常友好的界面体验。                     

       DWR 提供了一种使用 AJAX 的正确规范的方式。 DWR XMLHttpRequest 对象进行封装和隐藏,程序员在开发过程中只需要调用普通的 JS 方法就可以实现 AJAX 的异步调用功能,并且能够方便地处理返回值。因此在 GBP 框架中引入 DWR 可以有效解决滥用 AJAX 的问题,并且可以提高页面响应速度。另外,实践说明,使用 DWR 比使用 Struts 的开发效率更高。

如何使用 DWR

    在 GBP 框架中引入 DWR DWR 可以作为接收并处理用户请求的控件器存在,与目前系统中的 struts 处于同一层次。如此一来,程序员使用 DWR 的方式几乎与目前的 Struts 一致,学习成本较低,易于快速上手。下面以系统监控为例详细说明如何在 GBP 中使用 DWR

3.1    编写服务器端的 JAVA

    在 GBP 框架中, DWR 应该与 Struts 处于同一层次,它不是直接调用业务逻辑 BO ,而是根据统一编号调用相应 service ,再由 service 调用业务处理逻辑。类似 Struts 层的业务 Action DWR 也存在一个“业务 Action ”,系统监控对应的 DWR 业务 Action com.jiuqi.GBP.action.sysapp.msc.MscControl 类,该类的具体代码如下:

    类似于 Struts 中一个 Action 对应一个 ActionForm ,一般地,在 DWR 中,一个业务 form (相当于 Struts ActionForm )需要对应一个 DWR 的业务 Action 。系统监控模块通过 QueryConditionExtForm 封装所有的查询指标,因此只需一个 DWR 的业务 Action 即可处理所有请求。 MscControl 类通过 doService 方法可以实现一般情况下对 service 的调用,而 doQuery 方法则专用于分页查询。不同于 Struts 的业务 Action 一个请求必须对应一个方法并且需要在配置文件中提供导航配置的情况,使用 DWR 时上述两个方法可以处理系统监控模块的所有请求而且无需导航配置,代码数量大大减少。当然,实际项目开发过程中, DWR Action 可能需要对前台提交的参数做一些特殊处理,此时只需在 Action 中新起一个专门方法即可。

3.2   编写浏览器端的 Javascript 脚本

    以系统监控系统日志查询为例,了解一下 DWR 是如何通过 Javascript 脚本发送请求的。

    在系统日志查询主界面上点击“查询”按钮时触发如下 JS 脚本:

     其中 JS 对象 mscCtrl 就是 Java MscControl 类的 JS 映射,浏览器端 mscCtrl doQuery 方法的调用,通过 DwrServlet 处理转化为服务器端 MscControl 实例对 doQuery 方法的调用,实现查询请求处理。传入的最后一个参数 query_meta_obj 就是用于回调的 JS 对象,它接收服务器返回的数据传给回调函数进行处理, query_meta_obj 对象还封装了发送 DWR 请求时的其它参数。 query_meta_obj 对象代码如下:

 

    其中 callback 属性就是回调函数,用于接收查询结果数据,刷新列表显示结果:

    可以看到, DWRUtil.addRows 方法实现了对查询结果列表的更新。

    浏览器端对 DWR 的操作过程总结如下:

    可以看到, DWR 的处理流程很清晰,对开发人员而言,容易产生困难的地方可能就在回调处理方面,实现 DWR 回调需要一定的 JS 编码经验。脚本文件 /script/util/dwrutil.js 提供了一些通用的回调处理方法,可以作为参考。

3.3   配置文件

    DWR 的运行需要配置文件的支持。在 GBP 中引入 DWR ,首先需要修改 web.xml 文件并引入 DWR 本身的配置文件 dwr-GBP.xml ,还需要在 Spring 的配置文件中声明服务器端对象的 bean

    1 、在 web.xml DWR 作为一个 servlet 进行配置:

  <servlet> 
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<load-on-startup>5</load-on-startup>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<!-- Annotation -->
<init-param>
<param-name>classes</param-name>
<param-value>java.lang.Object</param-value>
</init-param>
<init-param>
<param-name>logLevel</param-name>
<param-value>DEBUG</param-value>
</init-param>
<init-param>
<param-name>config-user</param-name>
<param-value>WEB-INF/files/dwr-gbp.xml</param-value>
</init-param>
</servlet>

 

  配置其 URL 映射方式:

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

 

2 、在 DWR 配置文件 dwr-gbp.xml 中描述浏览器端与服务器端对象的转换关系:

<dwr>
<allow>
<convert converter="bean" match="com.xxx.gbp.formbean.form.*" />
<create creator="spring" javascript="mscCtrl">
<param name="beanName" value="mscControl" />
<include method="doService"/>
<include method="doQuery"/>
</create>
</allow>
</dwr>

上述配置表明,浏览器端对象为 mscCtrl ,服务器端对象是一个 Spring bean ,名为 mscControl ,故需要在 Spring 配置文件中声明。

 

结论: DWR 是否适合 GBP

    使用 DWR 的优点:

²  规范化应用 AJAX ,紧跟业界技术潮流;

²  提高界面响应速度,增强用户体验;

²  简化前台开发流程,减少代码量,提高开发效率;

²  GBP 的集成比较容易;

 

    DWR 是一个异步 AJAX 框架,非常适合处理异步类请求。但它并不是万能的,在有些方面使用 DWR 并不合适:

 

<!---->Ø  <!---->确实需要通过 Form 方式提交请求,如保存照片信息时;

<!---->Ø  <!---->处理文件上传下载请求;

<!---->Ø  <!---->处理导入导出请求;

<!---->Ø  <!---->构造树结构时,目前也无法用 DWR 改造;

 

    DWR 的优点十分明显,但在处理与 Servlet 耦合度比较高的请求时存在困难。

    另外, DWR 在高并发及大数据量情况下的表现尚未经过测试,我对此并不是很放心。

    综合 DWR 的优点与缺点,考虑到 GBP 的现有架构,推荐在 GBP 中引入 DWR 框架,做为控制层与 Struts 并存,开发过程中以 DWR 为主,以 Struts 为辅,充分发挥 DWR 的优势,在 DWR 不擅长的地方用 Struts 处理。

    推荐指数: ★★★★★

    技术难度: ★★☆☆☆

 

 

 

 

 

参考资料:

DWR 中文文档V0.9---- 方佳玮

Www.iteye.com 网站相关资料

 

分享到:
评论
4 楼 figcs2ut 2009-02-03  
文章写的很好,全面,学习啦!
3 楼 daoyongyu 2008-12-03  
好文章,学习了!
2 楼 niitstar 2008-11-21  
好文章。。。不过现在还没学dwr
1 楼 mmt 2008-04-27  
好文章,正在学习dwr,感谢分享!

相关推荐

Global site tag (gtag.js) - Google Analytics