当前位置: 代码迷 >> Web前端 >> 二零一三年11月15日-DWR的工作原理
  详细解决方案

二零一三年11月15日-DWR的工作原理

热度:352   发布时间:2013-11-23 10:52:51.0
2013年11月15日-DWR的工作原理
   接触DWR有一段时间了,但是只是学会了怎么用,项目上能实现功能就得了,一直不知道它的实现原理,今天晚上花时间了解了一下它的实现原理。
1、首先,DWR是通过Servlet是实现的,所以我们在web.xml中需要配置一个DWRServlet类。这样所有的/dwr/*所有请求都由这个servlet来处理。
2、DWR给我们做了一件伟大的事情,就是将Java转换为了JavaScript,这一步通过dwr.xml配置文件实现。dwr.xml中有两个重要的概念需要说一下:

creator在dwr中主要的职责就是把用户发布在dwr.xml中的class进行实例化,这样js中就可以使用这个对象调用Java类中的方法了,实现了客户端和服务器端的通信;
DWR提供的creator包括:jsf,none,new,pageflow,spring,script,struts
最常用的就是new,也就是实例化一个对象。

converter的职责是在接受请求时把客户端的javascript对象转换成服务器端的java对象,通过调用发布的java bean后,在把返回的java的对象转化成javascript的对象给客户端调用。
DWR提供的converter包括:null,enum,primitive,bignumber,string,array,map,collection, date,dom,dom4j,jdom,xom,servlet,bean,object,hibernate

如果DWR提供的creator和convertor不能满足需求,用户也可以自己创建自己的creator和convertor,只要将其发布在dwr.xml中就行了。

理解了这两个概念就可以很容易的看懂dwr.xml的配置了。

3、接下来看一下解析之后的文件:
由于配置了/dwr路径,web.xml中配置的DWR的DwrServlet会处理请求,然后将engine.js以流的形式发送给浏览器,同时它还会自动生成Hello.js ,并同样以流的形式发送给浏览器,这两个文件都可以在浏览器的缓存里找到。这两个文件在工程中是找不到的,如果不明白DWR的原理,很容易去工程的路径下找文件,可以怎么也找不到。(我开始的时候就是 )
以上次DWR用法中的Hello为例子,在浏览器中访问目录/dwr/interface/Hello.js(如果去看更里面的servlet的代码,就可以发现/interface/是要求配置成这样的,固定的)可以看到解析后的代码:


if (typeof dwr == 'undefined' || dwr.engine == undefined) throw new Error('You must include DWR engine before including this file');

(function() {
  if (dwr.engine._getObject("Hello") == undefined) {
    var p;
    
    p = {};
    p._path = '/DWRDemo1/dwr';

    /**
     * @param {class java.lang.String} p0 a param
     * @param {function|Object} callback callback function or options object
     */
    p.sayHello = function(p0, callback) {
      return dwr.engine._execute(p._path, 'Hello', 'sayHello', arguments);
    };

    /**
     * @param {function|Object} callback callback function or options object
     */
    p.getName = function(callback) {
      return dwr.engine._execute(p._path, 'Hello', 'getName', arguments);
    };

    /**
     * @param {class java.lang.String} p0 a param
     * @param {function|Object} callback callback function or options object
     */
    p.setName = function(p0, callback) {
      return dwr.engine._execute(p._path, 'Hello', 'setName', arguments);
    };
    
    dwr.engine._setObject("Hello", p);
  }
})();


看到代码中有这样一句话:
(1)if (typeof dwr == 'undefined' || dwr.engine == undefined) throw new Error('You must include DWR engine before including this file');
这就是为什么我们再写引用js的时候一定要将.engine写在最前面。engine.js和util.js,它们分别是dwr中的核心引擎库和辅助工具函数库!我们这里没有用到util.js的方法,可写可不写。util.js有一些处理table及select的方法,所以在实现中涉及到这两项是要把这个引用加上,或者为了保险起见可以每次将这两个引用都写在前面。

(2)从代码中可以看到,DWR引擎将dwr.xml中配置的javascript="Hello"映射为一个对象,将Java类的方法映射为了Js中的函数。其中每个函数都调用了_execute方法,这个方法完成初始化工作,其传入的参数有:
path――在/WEB-INF/web.xml配置的url-pattern,
scriptName――/WEB-INF/dwr.xml中creator的javascript的名称,
methodName――creator的方法名,
vararg_params――传进的值和一些控制参数
同样,在目录dwr/engine.js下也可以看到相应的代码,太长就不贴出来了。
4、调用DWR生成的.js函数:
调用方式:
.methodName(param1,...paramn,callback(msg));
callback是回调函数,用来回调java方法执行的结果。
这个回调方法是传到服务器端的,在服务器端很容易实现。回调方法的java的执行结果,返回类似 <script>callMethod(结果)<script>的javascript字符串,在浏览器执行。

至此,就完成了整个DWR的实现过程。


1 楼 liu765023051 2013-11-16  
很好,感谢楼主分享了。
  相关解决方案