dwr学习
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/dwr/
这段时间较闲,研究了一番dwr.发现dwr实现的AJAX有些地方确实很是先进.比如动态生成javascript代码;隐藏的http协议;javascript于java代码交互的是javascript对象(或字符串)等.
以下是我临时译的一些东西.本来想全译,发现dwr实在是简单,就随便写了.英文居差,现一把.
1、DWR: Easy AJAX for JAVA
作为一个java open source library,DWR可以帮助开发人员完成应用AJAX技术的web程序。
它可以让浏览器上的javascript方法调用运行在web服务器上java 方法。
DWR主要由两部门组成。
javascript与web服务器通信并更新web页;运行在web服务器的Servlet处理请求并把响应发回浏览器。
DWR采用新颖的方法实现了AJAX(本来也没有确切的定义),在java代码基础上动态的生成javascript代码。
web开发者可以直接调用这些javascript代码,然而真正的代码是运行在web服务器上的java code。
出与安全考虑,开发者必须配置哪些java class暴露给DWR.(dwr.xml)
这种从(java到javascript)调用机制给用户一种感觉,好象常规的RPC机制,或RMI or SOAP.但是它运行在web上,不需要任何浏览器插件。
DWR不认为浏览器和web服务器之间协议重要,把系统界面放在首位。
最大挑战是java method call的同步特征与ajax异步特性之间的矛盾。
在异步模型里,结果只有在方法结束后才有效。
DWR解决了这个问题,把回调函数当成参数传给方法,处理完成后,自动调用回调方法。
这个图表显示了,通过javascript事件,DWR能改变select的内容,当然这些内容由java代码返回。
javascript函数Data.getOptions(populateList)由DWR动态生成,这个函数会调用java class Data类的方法。
DWR处理如何远程调用,包括转换所有的参数和返回的结果(javascript\java)。
java方法执行完后,执行回调方法populateList。
在整个过程中我们就想在用本地的方法一样。
2、Getting Started
废话少说,试试就ok了。
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "/dtd/web-app_2_3.dtd">
<web-app id="dwr">
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> </servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
dwr.xml 与web.xml同目录
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="JDate">
<param name="class" value="java.util.Date"/>
</create>
</allow>
</dwr>
index.html
<html>
<head>
<title>DWR - Test Home</title>
<script type='text/javascript'
src='dwr/interface/JDate.js'></script>
<script type='text/javascript' src='dwr/engine.js'></script>
<script>
function init(){
JDate.getYear(load);
}
function load(data){
alert(data+1900+'年')
}
</script>
</head>
<body onload="init()">
</body>
</html>
dwr.jar 下载放lib下
完了,什么,够了,就这些。
访问ok!
3、Examples
/ 这不是Google Suggest吗!ok.
4、源码浅析
dwr的设计很象webwork2的设计,隐藏http协议,扩展性,兼容性及强。
通过研究uk.ltd.getahead.dwr.DWRServlet这个servlet来研究下dwr到底是如何工作滴。
Java代码
1.web.xml配置
2.<servlet>
3. <servlet-name>dwr-invoker</servlet-name>
4. <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-clas
s>
5. </servlet>
6. <servlet-mapping>
7. <servlet-name>dwr-invoker</servlet-name>
8. <url-pattern>/dwr/*</url-pattern>
9.</servlet-mapping>
10.这样所有的/dwr/*所有请求都由这个servlet来处理,它到底处理了些什
么能。
我们还以上面最简单的例子来看。
11.1、 web服务器启动,DWRServlet init()方法调用,init主要做了以下
工作。
12.设置日志级别、实例化DWR用到的单例类(这些类在jvm中只有一个实例
对象)、读去配置文件(包括dwr.jar包中的
dwr.xml,WEB-INF/dwr.xml. config*.xml)。
13.2、请求处理
14.DWRServlet.doGet, doPost方法都调用processor.handle(req, resp)
方法处理。
Processor对象在init()方法中已经初始化了。
15.<PRE class=java name="code">public void handle(HttpServletReque
st req, HttpServletResponse resp);
16. throws IOException
17. {
18. String pathinfo = req.getPathInfo();;
19. if(pathinfo == null || pathinfo.length(); == 0 || pathi
nfo.equals("/"););
20. {
21. resp.sendRedirect(req.getContextPath(); + req.getSe
rvletPath(); + '/' + "index.html");;
22. } else
23. if(pathinfo != null && pathinfo.equalsIgnoreCase("/inde
x.html"););
24. {
25. doIndex(req, resp);;
26. } else
27. if(pathinfo != null && pathinfo.startsWith("/test/"););
28. {
29. doTest(req, resp);;
30. } else
31. if(pathinfo != null && pathinfo.equalsIgnoreCase("/engi
ne.js"););
32. {
33. doFile(resp, "engine.js", "text/javascript");;
34. } else
35. if(pathinfo != null && pathinfo.equalsIgnoreCase("/util
.js"););
36. {
37. doFile(resp, "util.js", "text/javascript");;
38. } else
39. if(pathinfo != null && pathinfo.equalsIgnoreCase("/depr
ecated.js"););
40. {
41. doFile(resp, "deprecated.js", "text/javascript");;
42. } else
43. if(pathinfo != null && pathinfo.startsWith("/interface/
"););
44. {
45. doInterface(req, resp);;
46. } else
47. if(pathinfo != null && pathinfo.startsWith("/exec"););
48. {
49. doExec(req, resp);;
50. } else
51. {
52. log.warn("Page not found. In debug/test mode try vi
ewing /[WEB-APP]/dwr/");;
53. resp.sendError(404);;
54. }
55. }</PRE>
56.<BR>哦。
这些恍然大悟。
dwr/*处理的请求也就这几种。
57.<BR>(1)dwr/index.html,dwr/test/这种只能在debug模式下使用,调
试用。
58.<BR>dwr/engine.js,dwr/util.js,dwr/deprecated.js当这个请求到达,
从dwr.jar包中读取文件流,响应回去。
(重复请求有缓存)
59.<BR>(2)当dwr/interface/这种请求到来,(例如我们在index.html
中
的 <script type='text/javascript' src='dwr/interface/JDate.js'>
</script>)DWR做一件伟大的事。
把我们在WEB-INF/dwr.xml中的
60.<BR><create creator="new" javascript="JDate">
61.<BR> <param name="class" value="java.util.Date"/>
62.<BR></create>
63.<BR>java.util.Date转化为javascript函数。
64.<BR>http://localhost:port/simpledwr/dwr/interface/JDate.js看看
吧。
65.<BR>细节也比较简单,通过java反射,把方法都写成javascript特定的
方法。
(我觉得这些转换可以放到缓存里,下次调用没必要再生成一遍,不知道作者为什么没这样做)。
66.<BR>(3)dwr/exec
67.<BR> javascript调用方法时发送这种请求,可能是XMLHttpRequest
或IFrame发送。
68.<BR>当然,javascript调用的方法签名与java代码一致,包括参数,还
有javascript的回调方法也传到了服务器端,在服务器端很容易实现。
回调方法的java的执行结果返回类似 <script>callMethod(结
果)<script>的javascript字符串,在浏览器执行。
哈,一切就这么简单,巧妙。
69.<BR>
70.<BR>dwr的设计构思很是巧妙。
71.<BR>第一、把java类转化为javascript类由dwr自动完成,只需简单的
配置。
72.<BR>第二、应用起来极其简单。
开发者不要该服务器代码就可以集成。
73.<BR>第三、容易测试。
和webwork一样,隐藏的http协议。
74.<BR>第四、及强扩展性。
例如与spring集成,只需修改一点代码。
75.<BR>第五、性能。
就我与jason,等简单比较,dwr性能可能是最好的。
76.<BR>第六、自动把java对象转化为javascript对象,并且及易扩展。
1、最小配置
Java代码
1.<servlet>
2. <servlet-name>dwr-invoker</servlet-name>
3. <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
4.</servlet>
5.<servlet-mapping>
6. <servlet-name>dwr-invoker</servlet-name>
7. <url-pattern>/dwr/*</url-pattern>
8.</servlet-mapping>
2、当我们想看DWR自动生成的测试页(Using debug/test mode)时,可在
Java代码
1.servlet中加
2.<init-param>
3. <param-name>debug</param-name>
4. <param-value>true</param-value>
5.</init-param>
这个参数DWR默认是false.如果选择true.我们可以通过url
http://localhost:port/app/dwr ,你就可以看到你部署的每个DWR class。
并且可以测试java代码的每个方法是否运行正常。
为了安全考虑,在正式环境下你一定把这个参数设为false.
3、logging信息配置。
在无java.util.logging的jdk1.3下运行DWR,我们不希望强制用户加一个logging包,而是用HttpServlet.log()方法来输出日志。
如果classpath中包括logging jar包,DWR自动切换用logging输出日志。
如果用HttpServlet.log()方法,以下配置是有效的。
Java代码
1.<init-param>
2. <param-name>logLevel</param-name>
3. <param-value>DEBUG</param-value>
4.</init-param>
有效的值是 FATAL, ERROR, WARN (the default), INFO and DEBUG
我是喜欢用log4j输出日志,那么在log4j.properties下加,
.ltd.getahead.dwr = debug。
这样可以看DWR的调试日志。
4、多dwr.xml文件的配置
可能有几种情况,我们一一列举。
一个servlet,多个dwr.xml配置文件;多个servlet,每个servlet对应一个或多个dwr.xml.
一个servlet,多个dwr.xml配置文件;
Java代码
1.<servlet>
2. <servlet-name>dwr-invoker</servlet-name>
3. <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-clas
s>
4. <init-param>
5. <param-name>config-1</param-name>
6. <param-value>WEB-INF/dwr1.xml</param-value>
7. </init-param>
8. <init-param>
9. <param-name>config-2</param-name>
10. <param-value>WEB-INF/dwr2.xml</param-value>
11. </init-param>
12.</servlet>
在这种配置下,param-name的值必须以config开头。
param-name可以有>=0个。
如果没有param-name,那么将会读取WEB-INF/dwr.xml。
如果有大于零个param-name,那么WEB-INF/dwr.xml文件将不会被读取。
多个servlet,每个servlet对应一个或多个dwr.xml
Java代码
1.<servlet>
2. <servlet-name>dwr-invoker</servlet-name>
3. <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-clas
s>
4.<!--用classes/dwr.xml-->
5.</servlet>
6.<servlet>
7. <servlet-name>dwr-invoker1</servlet-name>
8. <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class
>
9. <init-param>
10. <param-name>config-admin</param-name>
11. <param-value>WEB-INF/dwr1.xml</param-value>
12. </init-param>
13. <init-param>
14. <param-name>debug</param-name>
15. <param-value>true</param-value>
16. </init-param>
17.</servlet>
18.<servlet-mapping>
19. <servlet-name>dwr-invoker</servlet-name>
20. <url-pattern>/dwr/*</url-pattern>
21.</servlet-mapping>
22.<servlet-mapping>
23. <servlet-name>dwr-invoker1</servlet-name>
24. <url-pattern>/dwr1/*</url-pattern>
25.</servlet-mapping>
在这种情况下,我们可以根据J2EE security来控制权限,针对不同url,加不同的角色。
5、dwr的几个扩展点(Plug-ins)
DWR对以下接口提供的默认的实现,用户可以继承DWR的默认实现类来达到我们想要的效果。
但这至少需要我们读了DWR源码才能做这些工作(dwr源码很是清晰,有兴趣可以学习一下),以后可能补存这部分。
Java代码
.ltd.getahead.dwr.AccessControl
.ltd.getahead.dwr.Configuration
.ltd.getahead.dwr.ConverterManager
.ltd.getahead.dwr.CreatorManager
.ltd.getahead.dwr.Processor
.ltd.getahead.dwr.ExecutionContext
1 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加入到下拉列表。
2 为什么使用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的开发效率更高。
3 如何使用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进行配置:
Xml代码
1.<servlet><BR>
2.
3.
4.
5.<servlet-name>dwr-invoker</servlet-name><BR>
6.
7.
8.
9.<servlet-class>org.directwebremoting.servlet.DwrServlet</servle
t-class><BR>
10.
11.
12.
13.<load-on-startup>5</load-on-startup><BR>
14.
15.
16.
17.<init-param><BR>
18.
19.
21. <param-name>debug</param-name><BR>
22.
23.
24.
25. <param-value>true</param-value><BR>
26.
27.
28.
29.</init-param><BR>
30.
31.
32.
33.<!-- Annotation --><BR>
34.
35.
36.
37.<init-param><BR>
38.
39.
40.
41. <param-name>classes</param-name><BR>
42.
43.
44.
45. <param-value>ng.Object</param-value><BR>
46.
47.
48.
49.</init-param><BR>
50.
51.
52.
53.<init-param><BR>
54.
55.
56.
57. <param-name>logLevel</param-name><BR>
58.
59.
60.
61. <param-value>DEBUG</param-value><BR>
62.
63.
65.</init-param><BR>
66.
67.
68.
69.<init-param><BR>
70.
71.
72.
73. <param-name>config-user</param-name><BR>
74.
75.
76.
77. <param-value>WEB-INF/files/dwr-gbp.xml</param-value><BR>
78.
79.
80.
81.</init-param><BR>
82.
83.
84.
85. </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配置文件中声明。
4 结论:DWR是否适合GBP?
使用DWR的优点:
✧规范化应用AJAX,紧跟业界技术潮流;
✧提高界面响应速度,增强用户体验;
✧简化前台开发流程,减少代码量,提高开发效率;
✧与GBP的集成比较容易;
DWR 是一个异步 AJAX 框架,非常适合处理异步类请求。
但它并不是万能的,在有些方面使用 DWR 并不合适:
∙ 确实需要通过 Form 方式提交请求,如保存照片信息时;
∙ 处理文件上传下载请求;
∙ 处理导入导出请求;
∙ 构造树结构时,目前也无法用 DWR 改造;
DWR 的优点十分明显,但在处理与 Servlet 耦合度比较高的请求时存在困难。
另外, DWR 在高并发及大数据量情况下的表现尚未经过测试,我对此并不是很放心。
综合 DWR 的优点与缺点,考虑到 GBP 的现有架构,推荐在 GBP 中引入 DWR 框架,做为控制层与 Struts 并存,开发过程中以 DWR 为主,以 Struts 为辅,充分发挥 DWR 的优势,在 DWR 不擅长的地方用 Struts 处理。
推荐指数:★★★★★
技术难度:★★☆☆☆
dwr 一些累积zz
dwr 一些累积
zhhzhfya 发表于2006-6-17 11:19:00
1、最小配置
java代码:
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
2、当我们想看DWR自动生成的测试页(Using debug/test mode)时,可在java代码:
servlet中加
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
这个参数DWR默认是false.如果选择true.我们可以通过url http://localhost:port/app/dwr ,你就可以看到你部署的每个DWR class。
并且可以测试java代码的每个方法是否运行正常。
为了安全考虑,在正式环境下你一定把这个参数设为false.
3、logging信息配置。
在无java.util.logging的jdk1.3下运行DWR,我们不希望强制用户加一个logging包,而是用HttpServlet.log()方法来输出日志。
如果classpath中包括logging jar包,DWR自动切换用logging输出日志。
如果用HttpServlet.log()方法,以下配置是有效的。
java代码:
<init-param>
<param-name>logLevel</param-name>
<param-value>DEBUG</param-value>
有效的值是FATAL, ERROR, WARN (the default), INFO and DEBUG
我是喜欢用log4j输出日志,那么在log4j.properties下加,.ltd.getahead.dwr = debug。
这样可以看DWR的调试日志。
4、多dwr.xml文件的配置
可能有几种情况,我们一一列举。
一个servlet,多个dwr.xml配置文件;多个servlet,每个servlet对应一个或多个dwr.xml.
一个servlet,多个dwr.xml配置文件;
java代码:
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>config-1</param-name>
<param-value>WEB-INF/dwr1.xml</param-value>
</init-param>
<init-param>
<param-name>config-2</param-name>
<param-value>WEB-INF/dwr2.xml</param-value>
</init-param>
</servlet>
在这种配置下,param-name的值必须以config开头。
param-name可以有>=0个。
如果没有param-name,那么将会读取WEB-INF/dwr.xml。
如果有大于零个param-name,那么WEB-INF/dwr.xml文件将不会被读取。
多个servlet,每个servlet对应一个或多个dwr.xml
java代码:
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<!--用classes/dwr.xml-->
</servlet>
<servlet>
<servlet-name>dwr-invoker1</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>config-admin</param-name>
<param-value>WEB-INF/dwr1.xml</param-value>
</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>
<servlet-mapping>
<servlet-name>dwr-invoker1</servlet-name>
<url-pattern>/dwr1/*</url-pattern>
</servlet-mapping>
在这种情况下,我们可以根据J2EE security来控制权限,针对不同url,加不同的角色。
5、dwr的几个扩展点(Plug-ins)
DWR对以下接口提供的默认的实现,用户可以继承DWR的默认实现类来达到我们想要的效果。
但这至少需要我们读了DWR源码才能做这些工作(dwr源码很是清晰,有兴趣可以学习一下),以后可能补存这部分。
java代码:
uk.ltd.getahead.dwr.AccessControl
uk.ltd.getahead.dwr.Configuration
uk.ltd.getahead.dwr.ConverterManager
uk.ltd.getahead.dwr.CreatorManager
uk.ltd.getahead.dwr.Processor
uk.ltd.getahead.dwr.ExecutionContext
1、DWR: Easy AJAX for JA V A
作为一个java open source library,DWR可以帮助开发人员完成应用AJAX技
术的web程序。
它可以让浏览器上的javascript方法调用运行在web服务器
上java方法。
DWR主要由两部门组成。
javascript与web服务器通信并更新web页;运行
在web服务器的Servlet处理请求并把响应发回浏览器。
DWR采用新颖的方法实现了AJAX(本来也没有确切的定义),在java代码
基础上动态的生成javascript代码。
web开发者可以直接调用这些javascript
代码,然而真正的代码是运行在web服务器上的java code。
出与安全考虑,
开发者必须配置哪些java class暴露给DWR.(dwr.xml)
这种从(java到javascript)调用机制给用户一种感觉,好象常规的RPC机制,
或RMI or SOAP.但是它运行在web上,不需要任何浏览器插件。
DWR不认为浏览器和web服务器之间协议重要,把系统界面放在首位。
最大挑战是java method call的同步特征与ajax异步特性之间的矛盾。
在异步模型里,结果只有在方法结束后才有效。
DWR解决了这个问题,把回调函数当成参数传给方法,处理完成后,自动调用回调方法。
这个图表显示了,通过javascript事件,DWR能改变select的内容,当然这些内容由java代码返回。
javascript函数Data.getOptions(populateList)由DWR动态生成,这个函数会调用java class Data类的方法。
DWR处理如何远程调用,包括转换所有的参数和返回的结果(javascript\java)。
java方法执行完后,执行回调方法populateList。
在整个过程中我们就想在用本地的方法一样。
2、Getting Started
废话少说,试试就ok了。
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "/dtd/web-app_2_3.dtd">
<web-app id="dwr">
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
dwr.xml 与web.xml同目录
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="JDate">
<param name="class" value="java.util.Date"/>
</create>
</allow>
</dwr>
index.html
<html>
<head>
<title>DWR - Test Home</title>
<script type='text/javascript' src='dwr/interface/JDate.js'></script>
<script type='text/javascript' src='dwr/engine.js'></script>
<script>
function init(){
JDate.getYear(load);
}
function load(data){
alert(data+1900+'年')
}
</script>
</head>
<body onload="init()">
</body>
</html>
dwr.jar 下载放lib下
完了,什么,够了,就这些。
访问ok!
3、Examples
/ 这不是Google Suggest吗!ok.
4、源码浅析
dwr的设计很象webwork2的设计,隐藏http协议,扩展性,兼容性及强。
通过研究uk.ltd.getahead.dwr.DWRServlet这个servlet来研究下dwr到底是如何工作滴。
java代码:
web.xml配置
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
这样所有的/dwr/*所有请求都由这个servlet来处理,它到底处理了些什么能。
我们还以上面最简单的例子来看。
1、web服务器启动,DWRServlet init()方法调用,init主要做了以下工作。
设置日志级别、实例化DWR用到的单例类(这些类在jvm中只有一个实例对象)、读去配置文件(包括dwr.jar包中的dwr.xml,WEB-INF/dwr.xml. config*.xml)。
2、请求处理
DWRServlet.doGet, doPost方法都调用processor.handle(req, resp)方法处理。
Processor对象在init()方法中已经初始化了。
java代码:
public void handle(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
String pathinfo = req.getPathInfo();
if(pathinfo == null || pathinfo.length() == 0 || pathinfo.equals("/"))
{
resp.sendRedirect(req.getContextPath() + req.getServletPath() + '/' + "index.html");
} else
if(pathinfo != null && pathinfo.equalsIgnoreCase("/index.html"))
{
doIndex(req, resp);
} else
if(pathinfo != null && pathinfo.startsWith("/test/"))
{
doTest(req, resp);
} else
if(pathinfo != null && pathinfo.equalsIgnoreCase("/engine.js"))
{
doFile(resp, "engine.js", "text/javascript");
} else
if(pathinfo != null && pathinfo.equalsIgnoreCase("/util.js"))
{
doFile(resp, "util.js", "text/javascript");
} else
if(pathinfo != null && pathinfo.equalsIgnoreCase("/deprecated.js"))
{
doFile(resp, "deprecated.js", "text/javascript");
} else。