【轉】反向AJAX

原文連接:http://blog.csdn.net/lccone/article/details/7743886javascript

反向Ajax的基本概念是客戶端沒必要從服務器獲取信息,服務器會把相關信息直接推送到客戶端。這樣作的目的是解決Ajax傳統Web模型所帶來的一個限制:實時信息很難從技術上解決。緣由是,客戶端必須聯繫服務器,主動詢問是否存在變動,若是有變動就會更新頁面(或者頁面的一部分)。雖然能夠很是快速完成這個操做,讓人感受好像是實時的,可是實際上不是實時的。咱們須要的是,服務器聯繫查看其頁面的全部瀏覽器,並通告所發生的變動。
反向Ajax是克服這個限制的一種方式。像Ajax自己同樣,這不是一門專門的技術,而是按照不尋常方式組合使用已有的技術達到不尋常的效果。
傳統的Web模式(也就是非Ajax的應用程序)有一系列鮮明的事件。簡單來講,用戶在客戶端的一個動做會致使向服務器發出一個請求,而後服務器按照請求進行相應處理,並把處理結果做爲響應傳回客戶端,這個響應一般是一個完整的新的UI視圖。這種處理過程反覆循環,直到用戶決定離開當前Web站點。在基於Ajax的應用程序的事件序列中,某個用戶動做會致使對某個客戶端Ajax引擎的調用,不論它是JavaScript代碼,仍是其餘庫。這個引擎會向服務器發出一個請求,服務器按照非Ajax模式進行處理,而後返回響應。響應內容首先被Ajax引擎處理,而後調用某些客戶端代碼以更新頁面。一樣,這個循環會無止境進行,直到用戶離開當前頁面。html

如今總共有三種DWR支持的技術能夠輔助完成這種技術,其中兩種技術都屬於"主動的"反向Ajax,第三種被認爲是"被動的"反向Ajax。下面逐個討論每種技術以及DWR提供的支持。java

 

7.9.1 輪詢
假設有個未使用AJAX的Web頁面,使用<meta>刷新標籤,每隔數秒就更新這個頁面。這就是所說的輪詢。客戶端定時輪詢服務器,看是否存在更新,而且顯示服務器傳回的當前信息。在網頁上,使用一些簡單的JavaScript代碼以持續地更新頁面,就能夠實現相同的事情。確實,可以從表面實現所謂的推送,這就是輪詢技術。
在Ajax中,事件流會更加複雜,可是實質上是同樣的,輪詢技術是兩種主動式反向Ajax方法的一種,客戶端在每一個時間週期內向服務器發送請求,看看服務器端有沒有數據更新,若是有,就向服務器請求數據。另外一種主動式方法被稱爲Comet。
7.9.2 Comet(服務器推)
第二種主動式反向Ajax方法是Comet,這是一種基於HTTP長鏈接的服務器推進方式。客戶端向服務器發送請求後,服務器將數據經過response發送給客戶端,但並不會將此response關閉,而是一直經過response將最新的數據發送給客戶端瀏覽器,直到客戶端瀏覽器關閉。使用 AJAX 實現「服務器推」與傳統的 AJAX 應用不一樣之處在於:
1. 服務器端會阻塞請求直到有數據傳遞或超時才返回。 
   2. 客戶端 JavaScript 響應處理函數會在處理完服務器返回的信息後,再次發出請求,從新創建鏈接。 
   3. 當客戶端處理接收的數據、從新創建鏈接時,服務器端可能有新的數據到達;這些信息會被服務器端保存直到客戶端從新創建鏈接,客戶端會一次把當前服務器端全部的信息取回。
7.9.3 PiggyBack(回傳)
PiggyBack(回傳)方法是DWR提供的一種「被動式」方法。服務器端將最新的數據排成隊列,而後等待客戶端下一次請求,接收到請求後就將等待更新的數據發給客戶端。DWR會使用默認的設置是PiggyBack,因此在默認狀況下,啓用反向Ajax時,不會致使服務器超載。
7.9.4 反向Ajax的配置與實現
要讓DWR程序支持反向AJAX,只須要在web.xml中DWRServlet裏添加一個初始化參數,添加內容爲:web

 
<servlet>  
    <servlet-name>dwr-invoker</servlet-name>  
    <display-name>DWR Servlet</display-name>  
    <description>Direct Web Remoter Servlet</description>  
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>  
<init-param>  
         <param-name>activeReverseAjaxEnabled</param-name>  
         <param-value>true</param-value>  
     </init-param>  
<init-param>  
</init-param>  
   </servlet>  
<servlet-mapping>  
    <servlet-name>dwr-invoker</servlet-name>  
    <url-pattern>/dwr/*</url-pattern>  
</servlet-mapping>  

 



若是應用的是輪詢技術,則須要添加中下參數:
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>
除了上述配置,爲啓用反向Ajax,在頁面中還須要一些JavaScript代碼,即:
dwr.engine.setActiveReverseAjax(true);
只須要上述代碼和web.xml文件中的配置,就能夠激活反向Ajax了。
處理輪詢請求的過程一般是在服務器端編寫一些代碼,以更新附加到服務器端的每一個客戶端的會話。DWR會記錄與之聯繫的每一個客戶端,分別存儲每一個客戶端的會話。這一點與一般的HTTP會話不一樣。藉助於此,能夠調用JavaScript代碼,下一個輪詢請求會通知這些調用。下面就是一個處理輪詢請求的例子,服務器端的發佈者實現代碼以下:ajax

package com.ajax.dwr;  
import java.util.LinkedList;  
import java.util.List;  
import org.directwebremoting.Browser;  
import org.directwebremoting.ScriptSessions;  
public class SendMessage {  
public void addMessage(String message) {  
   System.out.println("有客戶請求,消息爲:" + message);  
   messages.add(message);  
   Browser.withCurrentPage(new Runnable() {//啓用監聽客戶端當前頁線程  
            public void run() {//把數據添加到客戶端調用的方法中  
                ScriptSessions.addFunctionCall("receiveMessages", messages);  
            }  
        });  
}  
private List<String> messages = new LinkedList<String>();  
}  

 



這裏主要經過WebContext類得到DWR應用的WEB上下文,用ServletContext得到DWRServlet的上下文,以及經過WEB上下文獲取訪問本應用的客戶端瀏覽器的ScriptSession。一旦得到當前頁面的名稱,就能夠獲取當前鏈接到這個頁面的全部會話列表。而後,啓用監聽客戶端當前頁線程,把數據添加到客戶端調用的方法中。
下面是在客戶端執行的JSP頁面文件,代碼以下:瀏覽器

<html>  
<head>  
<base href="<%=basePath%>">  
<title>starting page</title>  
<script type="text/javascript" src="dwr/interface/SendMessage.js"></script>  
<script type="text/javascript" src="dwr/engine.js"></script>  
<script type="text/javascript" src="dwr/util.js"></script>  
<script type="text/javascript">  
   function sendMessage()  
   {  
    var message=$("message").value;  
    SendMessage.addMessage(message);  
   }  
   function receiveMessages(messages)  
   {  
     var chatlog = "";  
     for (var data in messages) {  
       chatlog = "<div>" + dwr.util.escapeHtml(messages[data]) + "</div>" + chatlog;  
     }  
     dwr.util.setValue("list", chatlog, { escapeHtml:false });  
   }  
</script>  
</head>  
<body onload="dwr.engine.setActiveReverseAjax(true);">  
input message:  
<input id="message" type="text" />  
<input type="button" value="send" onclick="sendMessage()" />  
<br>  
<div id="list"></div>  
</body>  
</html>  

 


Util類有不少很方便的方法,其中一個是setValue()。這個方法相似於在客戶端執行document.getElementById("list ").innerHTML = "",可是它會關注一些細節,好比目標元素是文本框或者其餘元素。在此,使用所記錄的Date域的當前值來更新list的內容。將第三個參數設爲true,能夠指定任何HTML內容,這樣的話不會破壞客戶端的任何內容
要用的java類在wr.xml文件配置內容以下:服務器

<create javascript="SendMessage" creator="new" scope="application">
           <param name="class" value="com.ajax.dwr.SendMessage"></param>
</create>

 


若是不但願使用輪詢方法,那麼能夠很是容易地切換爲用Comet方法,只須要把web.xml文件中以下代碼註釋掉:
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>

若是應用PiggyBack方法,則不須要在web.xml中DWRServlet裏添加上述初始化參數。
該例子中完整的web.xml配置內容以下;app

 
<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
<!-- 配置DWR的核心Servlet -->  
<servlet>  
   <!-- 指定DWR核心Servlet的名字 -->  
   <servlet-name>dwr</servlet-name>  
   <servlet-class>  
    <!-- 指定DWR核心Servlet的實現類 -->  
    org.directwebremoting.servlet.DwrServlet  
   </servlet-class>  
   <!-- 指定DWR核心Servlet處於調試狀態 -->  
   <init-param>  
    <param-name>debug</param-name>  
    <param-value>true</param-value>  
   </init-param>  
   <!-- 設置使用反向Ajax技術 -->  
   <init-param>  
    <param-name>activeReverseAjaxEnabled</param-name>  
    <param-value>true</param-value>  
   </init-param>  
   <init-param>  
    <param-name>  
     initApplicationScopeCreatorsAtStartup  
    </param-name>  
    <param-value>true</param-value>  
   </init-param>  
   <init-param>  
   <!--長鏈接只保持時間 -->>  
    <param-name>maxWaitAfterWrite</param-name>  
    <param-value>60</param-value>  
   </init-param>  
   <load-on-startup>1</load-on-startup>  
</servlet>  
<!-- 指定核心Servlet的URL映射 -->  
<servlet-mapping>  
   <servlet-name>dwr</servlet-name>  
   <url-pattern>/dwr/*</url-pattern>  
</servlet-mapping>  
<welcome-file-list>  
   <welcome-file>index.jsp</welcome-file>  
</welcome-file-list>  
</web-app>  

 


發佈文程序後,這裏爲了模擬多個用戶操做,先打開兩個窗口,而後在地址欄輸入http://localhost:8081/Ajaxapp/GetMessage.jsp,在出現的兩個頁面中,分別輸入不一樣的字符串後單擊「發送」按鈕,程序運行結果如圖7-5所示。從運行的結果能夠看出,當在一個頁面發消息時,另外一個頁面也顯示出的其餘頁面發送的消息。jsp

相關文章
相關標籤/搜索