DWR(Direct Web Remoting)是一个WEB远程调用框架.是一个开放源码的使用 Apache 许可协议的解决方案,它包含服务器端 Java 库、一个 DWR servlet 以及 JavaScript 库.它
为每一个服务器端的java对象生成一个javaScript对象,让前台开发的程序员,像使用本地javascript对象一样,去使用服务器端的java对象,而不必去关心网络的传输和参数类
型转化的细节
,其基本实现思想是对于服务器端每一个javabean,在客户端都会生成一个javascript对象。两个对象中的方法是一样的。当用户调用javascript对象的方法时,这个方法会通过网
络,去调用服务器端javabean,而这种通信过程,对用户来讲并不知情。
其搭建过程如下:
step 1. 配置 dwr 提供的Servlet .
* 导入 dwr.jar包
* 在 web.xml 中配置 dwr 的Sevlet,如下:
<servlet>
<servlet-name>dwrServlet</servlet-name>
<servlet-class>org.directwebremoting.servlet.DWRServlet</servlet-class>
<init-param> <!--此处开始的四行在测试时必须,否则会出现"Access to debug pages is denied. "信息.如果不写在正常使用时是不会受影响的,只是一个调试
设置而已-->
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwrServlet</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
step 2. 在dwr.xml 中配置代理
在<allow></allow>标签内插入如下内容:
<create javascript="要起的名字" creator="new">
<param name="class" value="包全名.类名"/>
</create>
如果是自己写的类那么配置如下内容,其实就是转换,意思是使用BeanConverter类进行转换.
<convert converter="bean" match="com.kettas.dwr.Student"/>
step 3. 测试 :http://localhost:8080/ajax/dwr
启动服务器后输入如下地址:ajax为工程名,dwr为在web.xml文件中配置的<url-pattern>/dwr/*</url-pattern>名
==========================================================================================================
如果函数使用了泛型,那么需要使用<signatures>标签.
<signatures>标签是用来声明java方法中List、Set或者Map参数所包含的确切类,以便java代码作出判断。
signatures段只是用来确定泛型参数中的类型参数。DWR会自己使用反射机制或者运行时类型确定类型,或者假设它是一个String类型。所以:
不需要signatures - 没有泛型参数: public void method(String p); public void method(String[] p);
需要signatures - DWR不能通过反射确定: public void method(List<Date> p); public void method(Map<String, WibbleBean> p);
不需要signatures - DWR能正确的猜出: public void method(List<String> p); public void method(Map<String, String> p);
不需要signatures - DWR可以通过运行时类型确定: public List<Date> method(String p);
没有必要让Javascript中的所有对象的key都是String类型 - 你可以使用其他类型作为key。但是他们在使用之前会被转换成String类型。DWR1.x用Javascript的特性把key转换成
String。DWR2.0可能会用toString()方法,在服务段进行这一转换。
<signatures> 写法如下:
<signatures>
<![CDATA[
import java.util.* ;//此处是导入所有要用到的包....
import com.kettas.dwr.*;
public List<Student> queryAllStudents() ;
]]>
</signatures>
注意:<signatures>和<allow>标签要写在同一级上面.
当我测试时把泛型(配置文件和java代码中的)都去掉了但是也没有报错,但为了严谨,还是都写上吧,至少不会错
=========================================================================================================
页面上的写法:
<html>
<head>
<script type='text/javascript' src='/ajax/dwr/interface/ 需要产生代理的请求.js'></script>
<script type="text/javascript" src="/ajax/dwr/engine.js"></script> <!--这个是必不可少的,详细看下面文档-->
</head>
<body></body>
</htm>
url a : /ajax/a.html //*此是访问时使用的url
URL b : /ajax/dwr/interface/JTestBean.js //*此是引入生成的js文件URL的写法,注意interface,所有生成的js文件都是在其下的.
============================================================================================================
下面将一个测试过程代码全部按顺序列出来:
***********************************
Student.java
package com.kettas.dwr ;
public class Student{
private Integer id ;
private String name ;
private int age ;
public Student(Integer id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
***************************************
TestBean.java
package com.kettas.dwr ;
import java.util.* ;
public class TestBean{
public String sayHello( String user ){
if( user == null || user.trim().length() == 0 ){
return "hello everyone !" ;
}else{
return "hello " + user + "!" ;
}
}
public List<Student> queryAllStudents(){ //在dwr.xml中是对此函数进行的泛型设置
try{
Thread.sleep( 3000 ) ;
}catch( Exception e ){}
List<Student> list = new ArrayList<Student>();
for( int i = 0 ; i < 2 ; i++ ){
Student stu = new Student();
stu.setId( i ) ;
stu.setName( "name" + i ) ;
stu.setAge( 10 + i ) ;
list.add( stu ) ;
}
return list ;
}
}
***************************************
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>dwrServlet</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwrServlet</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
***************************************
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>
<create javascript="JTestBean" creator="new">
<param name="class" value="com.kettas.dwr.TestBean"/>
</create>
<convert converter="bean" match="com.kettas.dwr.Student"/>
</allow>
<signatures> <!--函数使用了集合泛型时使用它-->
<![CDATA[
import java.util.* ;
import com.kettas.dwr.*;
public List<Student> queryAllStudents() ;
]]>
</signatures>
</dwr>
***************************************
=============================================================================================================
另附engine.js的简述一篇:
Engine.js的功能
Engine.js对DWR非常重要,因为它是用来转换乃至动态生成接口的javascript函数调用的,所以只要用到DWR的地方就需要它。
DWREngine.setTimeout()
允许你在call和batch级别调用元数据选项设置超时时间。全局的DWREngine.setTimeout() 函数应用于所有的DWR调用。设置这个值为0可以关闭调用的超时设置(默认就是0)。
setTimeout()的单位是毫秒,如果一个调用超时,那么相应的错误处理器将被调用。比如下面是一个调用级别设置超时的例子:
Remote.method(params, {
callback:function(data) { alert("it worked"); },
errorHandler:function(message) { alert("it broke"); },
timeout:1000
});
批量调用
使用batch来批量的执行远程调用。这样可以减少与服务器的交互次数,进而提高反应速度。例如:
DWREngine.begingBatch();
其它的功能操作...........
DWREngine.endBatch();
在批量处理中,DWR会小心的处理保证所有的回调函数都会被调用,注意:不能在batch里面执行同步调用,若batch中设置了不同的超时,只有最后一个是有效的。
--->ajax一般是异步进行的如果人为的让它顺序的执行可以用函数:
DWREngine.setOrdered(boolean)设置为true.但是这样会减慢应用程序
--->错误警告和超时
例子解析:
Remote.method(params, {
callback:function(data) { alert("it worked"); },
errorHandler:function(message) { alert("it broke"); },
timeout:1000
});
如果方法Remote.method调用在1000毫秒没有调用callback(回调函数),就开始执行下面的errorHandler函数,错误处理。
--->远程调用Hooks
DWREngine.setPreHook(function):在执行调用之前调用一个函数,但是没有参数传到这个函数(当你希望一些按钮在调用期间变灰来防止再次使用,这个功能会很有用)
DWREngine.setPostHook(function)与DWREngine.setPreHook(function)刚好相反
--->设置同步机制
DWREngine.setAsync(true);设置全局同步
Remote.method(params,{calback:function(data){......},async:true});设置局部同步
DWREngine.setMethod(newmethod)
newmethod必须是DWREngine.XMLHttpRequest或者DWREnginr.IFrame或者DWREngine.ScriptTag
举例:
-->DWREngine.setMethod(DWREnginr.IFrame); 全局的
-->Remote.method(params,{callback:function(data){.....},method:DWREnginr.IFrame}) 单次调用
-->DWREngine.beginBatch();
Remote.method1(params,callback1);
Remote.method2(params,callback2);
DWREngine.endBatch({method:DWREngine.IFrame});
DWREngine.setVerb(verb)设置传输的方法"get"或者"post"