`
鬼大来晚了
  • 浏览: 65965 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

2013年11月15日-DWR的工作原理

    博客分类:
  • DWR
阅读更多
   接触DWR有一段时间了,但是只是学会了怎么用,项目上能实现功能就得了,一直不知道它的实现原理,今天晚上花时间了解了一下它的实现原理。
1、首先,DWR是通过Servlet是实现的,所以我们在web.xml中需要配置一个DWRServlet类。这样所有的/dwr/*所有请求都由这个servlet来处理。

这里添加一段在stackoverflow上面看到的解释DWR的回答,写的非常到位。

In the simplest terms, DWR is an engine that exposes methods of server-side Java objects to JavaScript code. Effectively, with DWR, you can eliminate all of the machinery of the Ajax request-response cycle from your application code. This means your client-side code never has to deal with an XMLHttpRequest object directly, or with the server's response. You don't need to write object serialization code or use third-party tools to turn your objects into XML. You don't even need to write servlet code to mediate Ajax requests into calls on your Java domain objects.

DWR is deployed as a servlet within your Web application. Viewed as a black box, this servlet performs two major roles: First, for each exposed class, DWR dynamically generates JavaScript to include in your Web page. The generated JavaScript contains stub functions that represent the corresponding methods on the Java class and also performs XMLHttpRequests behind the scenes. These requests are sent to the DWR servlet, which, in its second role, translates the request into a method call on a server-side Java object and sends the method's return value back to the client side in its servlet response, encoded into JavaScript. DWR also provides JavaScript utility functions that help perform common UI tasks.

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  
很好,感谢楼主分享了。

相关推荐

Global site tag (gtag.js) - Google Analytics