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"