1.DWR是一个Java开源库,帮助你实现Ajax网站,它可以让你在浏览器中的Javascript代码调用Web服务器上的Java,就像在Java代码就在浏览器中一样。
2.DWR主要包括两部分:
在服务器上运行的Servlet来处理请求并把结果返回浏览器。
运行在浏览器上的Javascript,可以发送请求,并动态改变页面。DWR会根据你的Java类动态的生成Javascript代码。这些代码的魔力是让你感觉整个Ajax调用都是在浏览器上发生的,但事实上是服务器执行了这些代码,DWR负责数据的传递和转换。
2.1这种Java和Javascript之间的远程调用会让DWR用户感觉像是曾经习惯使用的RMI或SOAP的RPC机制。而且这一过程还不需要额外的浏览器插件。
2.2Java是同步的,而Ajax是异步的。所以当你调用一个远程方法时,你要给DWR一个回调函数,当数据从网络上回来时,DWR会调用这个函数。
3.DWR动态为服务端AjaxService类(Java)生成了一个相应的客户端AjaxService类(Javascript)。这个类被 eventHandler调用。DWR就会去处理整个远程调用的细节,包括在Javascript和Java之间转换参数和返回值。然后在这里例子中,它会执行你提供的回调函数(populateList),这个函数再利用DWR提供的工具函数来更改页面内容。
4.开发流程
如何开始用DWR
4.1. 安装DWR的Jar包
下载dwr.jar和commons-logging.jar文件。把它放到你的webapp的WEB-INF/lib目录下。那里可能已经有很多其他的jar文件了。
4.2. 编辑配置文件
需要把下面的代码加到WEB-INF/web.xml文件中。
<!-- 配置DWR的请求处理类 -->
<servlet>
<servlet-name>dwr_invoker</servlet-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr_invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
在WEB-INF目录下的web.xml旁边创建一个dwr.xml文件。可以从最简单的配置开始:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEdwrPUBLIC"-//GetAheadLimited//DTD Direct Web Remoting 3.0//EN""http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow><!--allow定义了DWR能够创建和转换的类 -->
<createcreator="new"javascript="DwrDate"><!--create为创建器 -->
<paramname="class"value="java.util.Date"></param>
</create>
<createcreator="new"javascript="DwrService">
<paramname="class"value="cn.jbit.dwr.service.DwrService"></param>
<!-- 设定暴露给客户端的方法-->
<includemethod="getDwrBean"></include>
</create>
<!-- 设定Bean 转换器-->
<convertconverter="bean"match="cn.jbit.dwr.service.DwrBean"></convert>
</allow>
</dwr>
DWR配置文件定义了那些DWR会创建提供远程调用的Javascript类。在上面的例子中我们定义了两个类来提供远程调用,并为其提供的Javascript类的名字。
在上面我们使用了new创建器,它会调用没有参数的构造函数来创建实例,但是所有JavaBean必须有这一构造函数。还要注意DWR有一些限制:
不要出现Javascript保留关键字;和保留关键字同名的函数指定被排除。
Javascript方法重载是不支持的,所以尽量不要再Java中使用。
4.2.1解释
<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAheadLimited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">
<dwr>
<init><!--用来声明创造bean的类和转换bean的类。-->
<creator id="..."class="..." />
<converter id="..." class="..."/>
</init>
<!--allow定义了DWR能够创建和转换的类 -->
<allow>
<!--创建器-->
<create creator=".<!--值有new和none new是新创建一个类:none适用于调用静态对象或存在的对象-->." javascript=".<!--在客户端创建的javascript对象命名-->." scope=".<!--作用域默认page-->."> <param name=".<!--参数-->."value="..."/>
<include method=".<!--定义允许访问的方法列表,其他默认不允许访问-->."/>
<exclude method=".<!--定义不允许访问的方法列表,其他默认允许访问-->."/>
</create>
<convert converter=".<!--类型转换器-->." match="..."/>
</allow>
<signatures> ... </signatures><!--使用反射来找出在转换时应该用那种类型。-->
</dwr>
--如果需要进行JavaBean对象和JavaScript对象之间的转换,需要在dwr.xml中显式设置
<convert converter="bean"match="www.dwrdemo.DwrBean">
<param name=".<!--参数-->."value="..."/>
</convert>
5. 访问下面的URL
http://localhost:8080/[YOUR-WEBAPP]/dwr/
你可以看见一个页面,里面有第二步中的类。接着往里点,你会看到所有可以调用的方法列表。这个页面是动态生成用来测试的例子。
另一种方式是看刚才的页面中提供的代码:
到 http://localhost:8080/\[YOUR-WEBAPP\]/dwr/ 页面,点击你的类。查看源码,找到执行方法的那几行,把那些文字粘贴到你的HTML或JSP中。
要包括下面这些能产生神奇效果的Javascript文件的链接。
<script src='/[YOUR-WEBAPP]/dwr/interface/[YOUR-SCRIPT].js'></script> <scriptsrc='/[YOUR-WEBAPP]/dwr/engine.js'></script>
例:<!-- 导入DWR 为Java 对象动态生成的JavaScript 文件-->
<scripttype="text/javascript" src="dwr/interface/DwrDate.js"></script>
<scripttype="text/javascript" src="dwr/interface/DwrService.js"></script>
<!--导入DWR 的JavaScript 文件-->
<scripttype="text/javascript" src="dwr/engine.js"></script>
<scripttype="text/javascript" src="dwr/util.js"></script>
5.1解释
engine.js对DWR非常重要,它是DWR客户端的核心,用来把动态生成的JavaScript对象转换为服务器上的Java对象
该函数库可用于设置一些DWR的全局属性
dwr.engine.setTimeout(time),以毫秒为单位设置请求超时的时间
dwr.engine.setHttpMethod(method),该方法只能设置两个值POST和GET
dwr.engine.setOrdered(boolean),Ajax通常都是异步调用,但服务器响应的顺序与调用顺序往往不同,使用dwr.engine.setOrfered(true)语句,DWR将保证请求的顺序与服务器响应的顺序一致
util.js文件中包含了一些工具函数,通过这些函数的帮助,将简化JavaScript操作
util.js提供一些基本的页面操作函数,通过这些函数可以方便的操作HTML元素
util.js文件与DWR框架关系不是特别大,可以在任何不同的网页中使用(即便该工程没有DWR支持)
$( )函数根据指定ID查找页面中的HTML元素
简单的讲
$(ID) = document.getElementById(ID)
使用 $() 使代码更简洁、更清晰
6.多个dwr.xml文件
可以有多个dwr.xml文件(详细信息见web.xml文档)。每个文件中的定义会被加在一起。DWR用这个功能来加载基础配置文件。我们可以看看标准被配置文件来了解dwr.xml的内容。
7.使用DWR的一些技巧
这里有些东西可以帮你使用DWR。如果你也有什么使用技巧,也添加进来吧。
创建一个"Google Suggest"组件
我不建议你做自己的suggest组件。让一些基础的东西工作起来是很容易的,但是让键盘导航正常的工作却不那么容易。有一些库里面已经包含的suggest组件:
Script.aculo.us 里有一个 Autocompleter.Local 函数,可以和DWR整合起来。让Local版的组件和DWR的远程调用结合起来要比直接让Remote版的组件工作起来更容易一些,因为Remote版的组件一般对服务器上的工作又特殊要求。你会可以在DWR的用户邮件列表中找到相关的信息,也可以看Rubens的blog
另外,Rimu Hosting的Peter实现了一个自己的Suggest组件,也是可以和DWR一起用的,查看这里
增强文件上传
Pierre Losson写了一个如何把DWR和Commons-Fileupload组件结合起来的文章。很不错,并且源码和演示都有。
改进加载信息
DWR 1.0 中的useLoadingMessage()函数有点问题,你可以自己定义这一信息,但是要小心调用。你也可以把这个函数中的问题修正一下。更多信息可以参看useLoadingMessage()的文档。
使用Server控制台
DWR可以报告出详细的错误信息,这些信息可以帮你找出你的程序错在哪里。如果你的程序出现什么异常,你应该仔细查看你的web容器开始或运行过程中出现的错误信息。一般错误信息会在WARNING或ERROR级别,但是INFO级别的信息也很有用。
如果你的log信息中又什么错误,但是你想知道的更详细的信息,可以查看INFO级别的信息,因为有时错误信息和后台信息会被一起输出到log里。
使用debug/test页面
debug/test页面对于查找错误也很有用。查看
http://localhost:8080/[YOUR-WEBAPP ]/
开始指南中有基本使用方法。但是一定要记住在发现错误时可以在这些页面找到有用的信息。
访问HttpServletRequest
向回调函数传递参数
通常我们需要把额外的信息传递给callback函数,但是所有的callback函数只有一个参数(远程方法的返回码)