DWR

一.DWR的全稱,官方網站的解釋以及定義,版本。
1.dwr的全稱是Direct Web Remoting(遠程web調用).
2.dwr的初衷可以用官方網站的一句話來表示:easy ajax for java.
3.dwr目前開發版本是dwr3.0,最高穩定版本是dwr2.0。
dwr的核心是ajax和java,它能夠在客戶端用js來調用java類。


二.什麼是Ajax,有何作用,執行流程,優缺點。
1.ajax的全稱是Asynchronous JavaScript and XML,Asynchronous的意思是用戶在發送請求之後
還可以在頁面上進行其他的操作。ajax不是一種新的技術,它是由javaScript和xml技術組成的。
2.ajax能夠使用戶在不提交整個頁面表單的情況下和服務器通信而取得需要的數據,而此時客戶操作不必阻塞。
從而提高頁面響應度,增強用戶體驗。
    3.ajax請求處理流程:
第一步、首先要創建一個xmlHttpRequest對象,它是一個javaScript對象用來發送請求。
根據瀏覽器對javaScript的支持來生成對象。
if (window.XMLHttpRequest) { 
http_request = new XMLHttpRequest(); 
} else if (window.ActiveXObject) {
http_request = new ActiveXObject("Microsoft.XMLHTTP"); 

第二步、然後就是通過onreadystatechange屬性來設置回調函數用來處理服務器返回的數據。
http_request.onreadystatechange = nameOfTheFunction; 
第三步、然後通過open方法來設置請求的方法(GET或者POST)、服務器的url、設置是否爲異步請求。
   http_request.open('GET', 'http://www.example.org/some.file', true);
第四步、通過send發送請求,可以發送值過去。
   http_request.send(null);
第五步、服務器處理完畢後調用回調函數並把數據傳過來。
第六步、之後檢查請求的狀態和HTTP響應情況就可以對數據進行處理了,數據的形式可以是xml形式或者text文本形式,
用DOM對xml數據進行解析。
if (http_request.readyState == 4) {//判斷服務器響應都已接受完畢
if (http_request.status == 200) {//表示信息已經成功返回
//這裏對數據進行解析
}
}
  ajax的優缺點:
優點:
1、節省了大量寬帶,降低了客戶端的響應時間。
2、使用異步方式與服務器通信,不需要打斷用戶的操作。
3、可以把以前一些服務器負擔的工作轉嫁到客戶端,利用客戶端閒置的能力來處理,減輕服務器和帶寬的負擔。
缺點:
1、ajax使瀏覽器後退失效,即對瀏覽器後退機制的破壞。
2、安全問題,ajax技術對企業數據建立了一個直接通道。這使得開發者在不經意間會暴露比以前更多的數據和服務器邏輯。
3、ajax不擅長於操作大數據,因爲數據以xml的形式從服務器端傳過來,客戶端用dom技術進行解析會非常的慢。
4、使用了javaScript技術,對瀏覽器的兼容情況不一。


三.相對Ajax而言,DWR的優缺點。
使用dwr的好處
DWR是對java的ajax封裝,它能夠使客戶端js調用服務端的java類並且取得數據,從而減小了ajax的複雜操作,
用dwr不用去考慮瀏覽器對js的支持程度。 
dwr的缺點:
比較的繁瑣,它必須要在web.xml進行配製servlet.要有dwr.xml文件,以及一個java類.


四.DWR的原理(根據web.xml來解析)
  使用DWR必須要在web.xml文件裏面配置DwrServlet,在配置DwrServlet的時候,指定了攔截的請求,默認是/dwr/*,
  當有請求符合條件的時候,DwrServlet進行攔截,攔截後根據頁面配置的dwr/interface/*.class,然後將×.class編譯成js。
五.如何來使用DWR.
  (1).首先到官方網站上下載jar包,然後導入工程。接着配置web.xml文件.
    <servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>  
<!--DWR默認是false.如果選擇true.就可以在URL後面加一個/dwr可以看到你部署的DWR class。例如:http://localhost:8080/demo/dwr-->
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
  (2).配置dwr.xml文件
    <create creator="new" javascript="Demo"> //Demo名稱意思是你在js裏面用的名稱。
<param name="class" value="com.lxit.Demo" /> //包名和類名
</create>
  (3).在jsp裏面導入:
    <script type='text/javascript' src='dwr/engine.js' />
    <script type='text/javascript' src='dwr/util.js' /> 
<script type='text/javascript' src='dwr/interface/Demo.js'>
這裏需要注意的是:dwr裏面並沒有Demo.js,而是我們配置的類必須要配置一個js。Demo就是類名,dwr/interface/也是不能改變的。
  (4).上面工作完成後開始調用:
     Demo類裏面有一個getUserById(long id),在js裏面就可以這樣來調用Demo.getUserById(1,dispose);
這裏注意dispose是一個js函數,爲了方便我這裏不寫dispose這個函數了。
意思就是說,服務器處理完後的結果交給dispose來處理。dispose就是一個回調函數。


六.json(JavaScript Object Notation)語法。
  (1).JSON是一種輕量級的數據交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。
  (2).語法:
    對象以{名稱:值,名稱:值}。每個名稱後跟一個":"後面是值,多個用","分開。
例如:var person={id:0,name:null};意思就是說,定義一個對象person,初始化id爲0,name爲null。
數組以[值,值]。例如:var array=[1,2,3];爲array數組賦了3個值。

七.使用的小技巧(顯示加載,調試JS,優化服務器性能)
1.顯示加載:DWR可以簡單實現頁面加載前提示,只要在函數裏寫上這個"dwr.util.useLoadingMessage()"方法就行了.


2.調試JS:DWR自帶了調試javaScript代碼的功能,只要在顯示的頁面的url從工程名以後截斷,再在尾部加上"/dwr",
   在出來的頁面中,會顯示java對象在js中的映射,從中可以看出哪些java對象被映射成了js對象,哪些沒有被映射
 在調試的過程中,每個方法後面都有一個execute的按鈕,點擊可以執行此方法


3.優化服務器性能:
1)CPU瓶頸:經過嚴格的測試DWR的性能沒什麼問題。DWR上性能消耗同web服務器和網絡比起來可以忽略不計。
 如果你真的需要提升DWR的性能的話,可以把log級別設置ERROR或FATAL,但是主要還是要看你的編碼情況。
2)Network瓶頸: DWR沒有管理你的瀏覽器緩存的功能,所以它會不斷的重複讀取DWR的javascript文件。
這裏有一個簡單的解決辦法,把javascript文件複製到你的web-app中,這樣web服務器就可以更好的利用它了。
  你也可以考慮把所有的javascript文件合併成一個文件,然後用DOJO的壓縮程序處理一個來節省流量。


八.分析dwr.xml
1.creator在dwr中主要的職責就是把配置在dwr.xml中的class進行實例化,
 creator屬性是必須的,它用來指定使用哪種創造器,創造器有以下幾種可供選擇:
new: 用Java的new關鍵字創造對象。
none: 它不創建對象,看下面的原因。 (v1.1+)
scripted: 通過BSF使用腳本語言創建對象,例如BeanShell或Groovy。
spring: 通過Spring框架訪問Bean。
jsf: 使用JSF的Bean。 (v1.1+)
struts: 使用Struts的FormBean。 (v1.1+)
pageflow: 訪問Beehive或Weblogic的PageFlow。 (v1.1+)


2.converter的職責是在接受請求時把客戶端的javascript對象轉換成服務器端的java對象,
 通過調用發佈的java bean後,再把返回的java對象轉化成javascript的對象給客戶端調用


九.註解
經常用到的註解主要有:@RemoteProxy、@RemoteMethod、@DataTransferObject和@RemoteProperty。
針對DWR對Javabean的註解分爲兩類:
Object和Class
針對Class的註解使用:
@RemoteObject註解類爲遠程反問class相等於create
@RemoteMethod 註解類爲遠程訪問方法相等於dwr.xml中白名單中註解的方法的應用的
注意默認的類中所有的方法爲全部在黑名單中。不可作爲遠程訪問對象的。
 
針對:Object使用@DataTransferObject 和@RemoteProperty註解接口
@DataTransferObject僅僅註解類對象
@RemoteProperty註解屬性和方法的應用


十:DWR反向異步技術(推拉技術,DWR2.0後最大的特性)
  1.借鑑思想
1.1:B/S(Browser/Server)結構與C/S(Client/Server)結構最大的區別就在於:
C/S結構需要部署特定客戶端,服務端可以主動的與客戶端進行通信;而B/S結構只有瀏覽器給服務端發送請求,才能獲得服務端的響應
    1.2:DWR的推技術就是借鑑了C/S的思想,在B/S結構中實現了服務端主動與客戶端通信,推技術的缺點就是:
當客戶端過多的時候,服務器的負載會很大。
    而拉技術就是普通的B/S的模式,發送請求才能獲得響應
  2.實現DWR推技術的三種模式
2.1:Polling(輪詢)
客戶端以一定的週期向服務器發送請求,看服務端是否有數據更新,如果有更新,就向服務端請求數據
2.2:Comet
客戶端向服務器發送請求後,服務器將數據通過response發送給客戶端,但並不會將此response關閉,而是一直通過response將最新的數
據發送給客戶端瀏覽器,直到客戶端瀏覽器關閉
2.3:Piggback(回傳)
服務器端將最新的數據排成隊列,然後等待客戶端下一次請求,接收到請求後就將更新的數據發給客戶端。
  3.實現方式
3.1 首先要讓我們的DWR程序支持反向異步技術,有二種方式:
1)在web.xml中配置DWR的時候,加入一個參數配置
<servlet>  
<servlet-name>dwr-invoker</servlet-name>  
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>  
<init-param>    
<param-name>activeReverseAjaxEnabled</param-name>    
<param-value>true</param-value>  
</init-param>
</servlet>
2)可以指定到具體的某個頁面支持反向Ajax
  指定頁面加載的時候:onload=dwr.engine.setActiveReverseAjax(true);
3.2 在服務端的java類裏面,先new一個Collection的對象,該構造方法所需要的參數是目標頁面的相對路徑和目標頁面的文件名
3.3 生成一個Util的對象,將Collection的對象作爲參數傳進去
3.4 通過頁面元素的id,將服務器端的數據發送到目標頁面的指定元素內

十一:DWR的動態table的實現
function pageInit{
QueryTools.queryAllProblem(function(problemList){  //調用服務端的java方法,將此方法返回的List集合做爲回調函數的參數
dwr.util.removeAllRows("peoplebody", { filter:function(tr) {  //清除表格的行,定義了一個過濾器,過濾掉不需要刪除的行
 return (tr.id != "pattern");    //清除表格內原來的所有行,除了id爲pattern的行(模板行)之外
}});
problemList.sort(function(p1, p2) { return p1.description.localeCompare(p2.description); });
//排序,調用集合的sort方法進行排序,p1.字段名.localeCompare(p2.字段名)表示按照該字段進行排序
var problem;
var problemId;
for (var i = 0; i < problemList.length; i++) { //以數組的方式來遍歷集合
 problem = problemList[i];
 problemId = problem.id;
 dwr.util.cloneNode("pattern", { idSuffix:problemId });  
//"pattern"是頁面上定義的一個表格行的模板,cloneNode方法是複製一個節點,也就是將頁面上的"pattern"節點複製一條,
//並將其元素id在"pattern"的基礎上加上後綴:problemId
 dwr.util.setValue("table從" + problemId, problem.description);
//"tableDescription"是"pattern"模板行中的單元格的id,讓其加problemId是爲了避免頁面上的元素id重複,然後將對象的對應字段值放進單元格
 dwr.util.setValue("tableTpye" + problemId, problem.type);
 dwr.util.setValue("tableState" + problemId, problem.state);
 dwr.util.setValue("tableDate" + problemId, problem.submitDate);
 dwr.util.setValue("tableQuizuser"+problemId,problem.loginName);
 $("pattern" + problemId).style.display = "table-row";
//設定複製出來的這一行的顯示風格,"table-row"表示作爲表格的行來顯示
 problemCache[problemId] = problem;
//problemCache是一個緩存數組,將查詢出來的對象放進這個緩存數組內
}
});
}

function delete(elementId) { //刪除的方法
 var deletePrefix = "delete";  //這個是查詢頁面的表格上,每一行的最後一列的"刪除"按鈕的id,它是在"delete"的後面加上該行對象的id
 var problem = problemCache[elementId.substring(deletePrefix.length)]; //獲取該行對象的id
 if (confirm("Are you sure you want to delete?")) {
 dwr.engine.beginBatch();  //啓動一個批處理,注意:修改,刪除的方法都必要在DWR批處理裏面才能執行
 QueryTools.deleteProblem(problem.id); //調用刪除方法,將指定的id傳入後臺
 pageInit(); //刪除以後,重新查詢數據,所以再調用上面的pageInit方法
 dwr.engine.endBatch();
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章