DWR框架实现AJAx

来源:互联网 发布:扫描字体识别软件 编辑:程序博客网 时间:2024/05/02 01:47

DWR 框架实现ajax
客户端--js
服务端--servlet+xml 
两者--》服务端的后台组件(类)通过js代码,来调用。
需要用到得dwr包:dwr.jar,commons-logging.jar包
将DwrServelet配置在web.xml中,它是用来1 接受前台对后端组件得调用请求,并完成对后台组件得创建和调用
                                                              2 向客户端动态生成操作所需得js代码
注:dwr框架的请求会和Struts框架请求action发生冲突,但是可以通过formbean,所以一般情况尽量不整合在一起,但是可以和 spring整合。
<servlet>
    <servlet-name>dwrServlet</servlet-name>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <init-param>
      <param-name>classes</param-name>
      <param-value>java.lang.Object</param-value>
    </init-param>
  </servlet>

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

----------------------------------
在dwr.xml中
<create>--通过dwr框架可直接访问得后台组件
  -creator:new Dwr框架创建组件得实例对象
            spring 通过Spring框架访问bean,获取对象得引用
            Struts:Dwr通过会话,访问struts所创建ActionForm对象
            none.不创建对象
  -javascript  设定能访问得js对象名和js文件名 <script src="dwr/对象名.js"/>
  -scope
  -param
<convert>---将java中得定义或者API已有的数据封装结构,转化为js中得合法数据类型
  -converter属性--转换类型
         array-数组类型
         bean-class类型
         collection/map-键值对映射类型
         enum-枚举类型
  -match属性---将后台待转换得类型

 

dwr.xml
<dwr>
  <allow>
     <create creator="new" javascript="DAO">
         <param name="class" value="cn.com.dao.impl.DaoImpl"/>//value是完整得dao类名,若是creator="spring"  那么需要name="bean" 
     </create>
     <convert match="cn.com.vo.UserVo"/>
     </convert>
  </allow>
</dwr>
----------------------------------
<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
这两个js是dwr在js上操作特有得js文件,虽然无需导入,但是在js文件中需要声明
<script type="text/javascript" src="dwr/interface/DAO.js"></script>//这个是我们自动生成得js

DWR-js常用方法!
<script type="text/javascript" >
  function query(){
       DAO.findByAll(前面是方法得参数列表,getResult); 最后getResult是获取返回值
  }
  function getResult(list) {
   DWRUtil.removeAllRows("myBody");
   DWRUtil.addRows("myBody",list,user);
   
  }
  
  var user = [//这个是一个模板,这样的模板才能出结果,是按什么形式输出都是可以的。
   function(userVO){return userVO.name;},
   function(userVO){return userVO.age;},
   function(userVO){return userVO.sex;},
   function(userVO){return userVO.sal;}
  ];
</script>

======================================================================

以下是网上的学习入门资料,基本上都能看懂,关键是了解DWR框架的优势和缺点

 

DWR(Direct Web Remoting)是一个开放源码的使用 Apache 许可协议的解决方案,它包含服务器端 Java 库、一个 DWR Servlet 以及 JavaScript 库。虽然 DWR 不是 Java 平台上唯一可用的 Ajax-RPC 工具包,但是它是最成熟的,而且提供了许多有用的功能。为什么要使用DWR,我们首先介绍基本AJAX流程,从中可以看到引入DWR会带来什么好处。

1、AJAX的基本介绍
    Ajax (Asynchronous JavaScript And XML)描述了一种使用混合了HTML(或XHTML)和层叠样式表作为表达信息,来创建交互式的Web应用的开发技术;文档对象模型(DOM)、JavaScript、动态地显示和与表达信息进行交互;并且,XMLHttpRequest对象与Web服务器异步地交换和处理数据。
    使用AJAX,我们可以开发出有很好交互性的B/S程序,同时AJAX局部和异步刷新的特性也大大减小了对服务器和网络的压力。对于非AJAX的B/S程序来说HTML、DOM、JS同样是不可或缺的关键技术,因此引入AJAX技术主要是增加了对于XMLHttpRequest对象的使用。我们使用AJAX来开发一个简单的AJAX程序。
例1:
服务端的TestAjaxServlet:

public void doPost(HttpServletRequest req, HttpServletResponse res) throws java.io.IOException { res.getWriter().write("Getting Message uses AJAX directly!"); }


请将些Servlet配置成ajax/testAjaxServlet.
客户端的使用AJAX去调用服务端的TestAjaxServlet并响应:

function getAjaxMessage() { var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { http_request.overrideMimeType("text/html"); } } else { if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } } if (http_request === false) { alert("Cannot create XMLHTTP instance"); return false; } http_request.onreadystatechange = function () { document.getElementById(‘MessageSpan’).innerHTML = http_request.responseText; }; http_request.open("POST", “ajax/testAjaxServlet.do“, true); http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http_request.setRequestHeader("Content-length", parameters.length); http_request.setRequestHeader("Connection", "close"); http_request.send(parameters); }


当客户端调用getAjaxMessage()成功后,页面上的“MessageSpan”部分会出面“Getting Message uses AJAX directly!”,表明调用成功,且页面没有整体全部的刷新,在处理没有完成的时候,用户和页面上其它的UI交互并不受影响。
与传统B/S开发方法相比,服务端代码没有受到影响,客户端使用则需要创建XMLHttpRequest对象与服务端进行交互,同时在服务端调用完成后,使用JS回调函数处理服务端返回的数据。AJAX为B/S程序带来了种种好处的同时,也带来了下列问题,一是需要使用XMLHttpRequest对象,二是如果服务端想要返回一个复杂的数据结构时,一般只能返回XML代码,虽然有很多相对应的工具来解析XML,但还是增加了较大的工作量,有没有一种方法或工具,能够封装XMLHttpRequest,屏蔽HTTP协议细节,不会对服务端的代码造成影响,同时能让将服务端返回的复杂数据结构隐式转换为客户端JS程序可以直接使用的数据结构?有,答案就是DWR。

2、DWR框架基本介绍
    从最简单的角度来说,DWR 是一个引擎,可以把服务器端 Java 对象的方法公开给 JavaScript 代码。使用 DWR 可以有效地从应用程序代码中把 Ajax 的全部请求-响应循环消除掉。这意味着客户端代码再也不需要直接处理 XMLHttpRequest 对象或者服务器的响应。不再需要编写对象的序列化代码或者使用第三方工具才能把对象变成 XML。甚至不再需要编写 servlet 代码把 Ajax 请求调整成对 Java 域对象的调用。
    DWR 是作为 Web 应用程序中的 servlet 部署的。把它看作一个黑盒子,这个 servlet 有两个主要作用:首先,对于公开的每个类,DWR 动态地生成包含在 Web 页面中的 JavaScript。生成的 JavaScript 包含存根函数,代表 Java 类上的对应方法并在幕后执行 XMLHttpRequest。这些请求被发送给 DWR,这时它的第二个作用就是把请求翻译成服务器端 Java 对象上的方法调用并把方法的返回值放在 servlet 响应中发送回客户端,编码成 JavaScript。DWR的标准流程如下图所示:

diyblPic

页面触发eventHandler()事件,事件内部调用了AjaxService.getOptions方法,当调用完成后,利用服务端返回的数据用客户端的populateList()方法进行数据展现。
我们通过一个简单的DWR示例来说明如何使用DWR。
为了使用DWR,需要将DWR的jar文件拷入Web应用的WEB-INF/lib目录中(可在http://getahead.org/dwr下载),在web.xml中增加一个servlet声明,并创建DWR的配置文件。
服务端的配置:

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


在WEB-INF中创建文件dwr.xml:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd"> <dwr> <allow> </allow> </dwr>


服务端的TestDWR:

public String getMessage() { return "Getting Message uses DWR!"; }


在dwr.xml的<allow></allow>中增加如下内容:

<create creator="new" javascript="TestDWR"> <param name="class" value="ajax.TestDWR"/> </create>


至此,服务端的配置已经完成,如果有新的功能增加,只需要对在dwr.xml中进行相应的配置即可。
客户端的配置:
如果页面要使用DWR,需要将下面三行引入:
<script src='/[YOUR-WEBAPP]/dwr/interface/[YOUR-SCRIPT].js'></script>
<script src='/[YOUR-WEBAPP]/dwr/engine.js'></script>
在页面中增加如下代码定义JS函数:

<script> function getDWRMessage () { TestDWR. getMessage (showMessage); } function showMessage(data) { document.getElementById(‘MessageSpan’).innerHTML = data; } </script>


当客户端调用getDWRMessage ()成功后,页面上的“MessageSpan”部分会出面"Getting Message uses DWR!",表明DWR调用成功,且页面没有整体全部的刷新,在处理没有完成的时候,用户和页面上其它的UI交互并不受影响。
    对例1和例2进行对比,我们可以发现使用DWR开发B/S应用时,DWR为我们屏蔽了HTTP协议的细节,不再需要使用XMLHttpRequest对象来与服务器进行交互,解决了我们在编写AJAX应用时一个较大的问题,但在例2中我们中只返回了一个简单的字符串,如果我们希望返回一个较复杂的数据结构,如一个对象数组,DWR又如何解决这个问题呢?
例3:
定义一个Java Bean:

public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }


在dwr.xml的<arrow></arrow>间增加如下内容:

<convert converter="bean" match="ajax.User"> </convert>


在现有的服务端代码中增加一个方法:

public ArrayList getUserList(){ ArrayList userList = new ArrayList(); User userA = new User(); userA.setUsername("John"); userA.setPassword("123456"); userList.add("userA"); User userB = new User(); userB.setUsername("Tom"); userB.setPassword("123456"); userList.add("userB"); return userList; }


在客户端,我们增加一个JS函数来调用服务端的getUserList方法

Function getUserListFromServer(){ Util.getUserList({callback:function(dataFromServer){ for(var i = 0; i < dataFromServer.length; i++){ alert(dataFromServer[i].username); } }}); }


当触发页面的getUserListFromServer方法后,“John”, “Tom”顺序显示,这样,我们直接使用服务端定义的一个对像数组,就像js中定义的一样,不需要我们手工进行转换。

3、DWR框架的缺点
    通过上面的示例程序,我们可以看到使用DWR开发B/S程序给我们带来了很大的便利,但任何技术都有不足之处,对这些不足之处的充分了解,有助于我们更好的理解DWR的适用范围,发挥它的优点。
    同任何 RPC 机制一样,在 DWR 中,可能很容易忘记对于远程对象进行的每个调用都要比本地函数调用昂贵得多。DWR 在隐藏 Ajax 的机械性方面做得很好,但是重要的是要记住网络并不是透明的 —— 进行 DWR 调用会有延迟,我们不能因为某些实现上的问题,将完全可由客户端完成的功能转交服务端完成,这样会导致服务器和网络增加了不必要的开销。
    DWR在一定程度上造成了客户端和服务端形成耦合,因为客户端“直接”调用服务端的方法,因此接口的变更会对两者都造成影响。
在例1的AJAX程序中,虽然是用XMLHttpRequest对像来发起对服务器的请求,但对服务器来说与普通的页面提交没有区别,因DWR却是直接调用了Server端的函数,因为对于标准AJAX来说非常简单的功能对DWR来说却无法完成,以基于Struts的B/S应用为例,当客户端提交一个请求时,框架会首先获取此请求,进行相应的预处理,创建准备调用的Action所需的各种数据对像后,最终才会调用Action中对应的方法,但是DWR调用时,Struts框架被绕过了,Action所需的各种数据对像无法生成,因此也就无法调用。

4、DWR框加的高级话题
A.配置服务端方法的可调用范围
    在以上的2个DWR示例中,我们配置了两个JAVA类,将它们的所有属性和方法都暴露给了客户端,为了提高安全性,我们通常在dwr.xml中应该只配置那些客户端需要使用的方法和属性。DWR支持对dwr.xml更细粒度的配置来提高安全性,我们先看一下与配置有关的两个元素:
create 元素
    create 元素告诉 DWR 应当公开给 Ajax 请求的服务器端类,并定义 DWR 应当如何获得要进行远程的类的实例。这里的 creator 属性被设置为值 new,这意味着 DWR 应当调用类的默认构造函数来获得实例。其他的可能有:通过代码段用 Bean 脚本框架

------------------------------------------------------编程遇到的错误:

最后编写程序时,一直遇到这样一个问题:

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.directwebremoting.dwrp.PollHandler.<clinit>(PollHandler.java:443)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.directwebremoting.impl.ContainerUtil.class$(ContainerUtil.java:97)
at org.directwebremoting.impl.ContainerUtil.setupDefaults(ContainerUtil.java:150)
at org.directwebremoting.impl.ContainerUtil.setupDefaultContainer(ContainerUtil.java:125)
at org.directwebremoting.servlet.DwrServlet.init(DwrServlet.java:73)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:133)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:216)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:634)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:445)
at java.lang.Thread.run(Unknown Source)
2008-10-28 9:24:46 org.apache.catalina.core.StandardWrapperValve invoke

后来仔细分析才明白,缺少commons-logging.jar  这个包,这个包是随着struts中的导入,其中的一个包。

 

在项目中导入dwr.jar包和commons-logging.jar包,commons-logging.jar包一定要,否则会报错 !!记住!

原创粉丝点击