傳統模式的 Web 系統以客戶端發出請求、服務器端響應的方式工做,服務端不能主動發送請求(消息)給客戶端。
這種方式並不能知足不少現實應用的需求,譬如:
監控系統:後臺硬件熱插拔、LED、溫度、電壓發生變化;
即時通訊系統:其它用戶登陸、發送信息;
即時報價系統:後臺數據庫內容發生變化;
這些應用都須要服務器能實時地將更新的信息傳送到客戶端,而無須客戶端發出請求。「服務器推」技術在現實應用中有一些解決方案,這些解決方案大體能夠分爲兩類:
一類須要在瀏覽器端安裝插件,基於套接口(Socket)傳送信息,或是使用 RMI、CORBA 進行遠程調用;而另外一類則無須瀏覽器安裝任何插件、基於 HTTP 長鏈接。
而基於客戶端套接口的「服務器推」技術大致能夠分爲:
1.傳統輪詢:在 Web 早期,這一點常使用 meta 刷新實現。這將自動指示瀏覽器在指定秒數以後從新裝載頁面,從而支持簡陋的輪詢( polling )。例如在 HTML 文件中加入 <META HTTP-RQUIV="Refresh" CONTENT=12> ,實際上就是 HTTP 頭標告知瀏覽器每 12 秒更新一次文檔。
優勢:不須要服務器端配置
缺點:用戶體驗度差
對服務器的壓力很大,帶寬流失嚴重
2.ajax輪詢:Ajax 隔一段時間(一般使用 JavaScript 的 setTimeout 函數)就去服務器查詢是否有改變,從而進行增量式的更新。可是間隔多長時間去查詢成了問題,由於性能和即時性形成了嚴重的反比關係。間隔過短,接二連三的請求會沖垮服務器,間隔太長,務器上的新數據就須要越多的時間才能到達客戶機。
優勢:不須要太多的服務器端配置
下降了帶寬的負荷(由於返回的不是完整的頁面)
缺點:對服務器的壓力並無減小
實時性差,有必定的延遲
應用:這種技術很常見,不少webmail應用程序就是經過這種技術在電子郵件到達時顯示電子郵件的。
3.comet:Comet 方式通俗的說就是一種長鏈接機制 (long lived http) 。一樣是由 Browser 端主動發起請求,可是 Server 端以一種彷佛很是慢的響應方式給出回答。這樣在這個期間內,服務器端可使用同一個 connection 把要更新的數據主動發送給 Browser 。所以請求可能等待較長的時間,期間沒有任何數據返回,可是一旦有了新的數據,它將當即被髮送到客戶機。Comet 又有不少種實現方式,可是總的來講對 Server 端的負載都會有增長 . 雖然對於單位操做來講,每次只須要建議一次 connection, 可是因爲 connection 是保持較長時間的 , 對於 server 端的資源的佔用要有所增長。
優勢:實時性好(消息延時小);性能好(能支持大量用戶)
缺點:長期佔用鏈接,喪失了無狀態高併發的特色。
應用:股票系統。實時通信。
4.flash xml socket:這種方案實現的基礎是:1、 Flash 提供了 XMLSocket 類。2、 JavaScript 和 Flash 的緊密結合:在 JavaScript 能夠直接調用 Flash 程序提供的接口。
優勢:實時性好(消息延時小);性能好(能支持大量用戶)
缺點:由於 XMLSocket 沒有 HTTP 隧道功能, XMLSocket 類不能自動穿過防火牆;
由於是使用套接口,須要設置一個通訊端口,防火牆、代理服務器也可能對非 HTTP 通道端口進行限制;
應用:網絡聊天室,網絡互動遊戲。
5.java appet:在客戶端使用 Java Applet ,經過 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 創建與服務器端的套接口鏈接,從而實現 「 服務器推送 」 。
DWR採用的是長鏈接機制。
一、長鏈接技術經過客戶端發出請求獲取服務器端數據的方式一般稱爲"拉"技術,很形象說明客戶端在拉取服務器端數據,而有時候須要服務器端主動向客戶端"推"數據,好比監測聊天上線人數主動向上線發送消息,後臺數據庫發生變化是主動更新全部客戶端展現。
二、Reverse Ajax實現服務器推技術DWR2.x的推技術也叫DWR Reverse Ajax(逆向Ajax)主要是在BS架構中,從服務器端向多個瀏覽器主動推數據的一種技術。DWR的逆向Ajax主要包括兩種模式:主動模式和被動模式。其中主動模式包括polling和comet兩種,被動模式只有piggyback這一種:
(1)piggyback方式,是默認的方式。若是後臺有什麼內容須要推送到前臺,是要等到那個頁面進行下一次ajax請求的時候,將須要推送的內容附加在該次請求以後,傳回到頁面。只有等到下次請求頁面主動發起了,中間的變化內容才傳遞迴頁面。
(2)comet方式當服務端創建和瀏覽器的鏈接,將頁面內容發送到瀏覽器以後,對應的鏈接並不關閉,只是暫時掛起。若是後面有什麼新的內容須要推送到客戶端的時候直接經過前面掛起的鏈接再次傳送數據。服務器所能提供的鏈接數目是必定的,在大量的掛起的鏈接沒有關閉的狀況下,可能形成新的鏈接請求不能接入,從而影響到服務質量。
(3)polling方式由瀏覽器定時向服務端發送ajax請求,詢問後臺是否有什麼內容須要推送,有的話就會由服務端返回推送內容。這種方式和咱們直接在頁面經過定時器發送ajax請求,而後查詢後臺是否有變化內容的實現是相似的。 javascript
2.ScriptSession的生命週期
客戶端每次請求(刷新)都會生成一個新的ScriptSession,當客戶端請求時或者客戶端退出時將會銷燬ScriptSession。
經過ScriptSession咱們能夠獲得客戶端(瀏覽器)的腳本執行權。即咱們能夠直接調用瀏覽器的js代碼。
本節Demo實現的基本功能:
在上節(
DWR3.0框架入門(1) —— 實現ajax
)的代碼基礎上修改,實現將index.jsp輸入框中的推送文本顯示在其它打開的jsp頁面上
3.Demo修改的流程
1.修改MessagePush中的send方法:
package sugar.dwr;
import java.util.Collection;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
public class MessagePush {
public void send(final String content){
Runnable run = new Runnable(){
private ScriptBuffer script = new ScriptBuffer();
public void run() {
//設置要調用的 js及參數
script.appendCall("show" , content);
//獲得全部ScriptSession
Collection<ScriptSession> sessions = Browser.getTargetSessions();
//遍歷每個ScriptSession
for (ScriptSession scriptSession : sessions){
scriptSession.addScript( script);
}
}
};
//執行推送
Browser. withAllSessions(run);
}
}
2.新建receiver.jsp用來接收來自服務器的消息:
<%@ page language= "java" import ="java.util.*" pageEncoding="UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head >
<title >dwr接收</title >
<script src="js/jquery-1.8.3.js" ></script>
<script type="text/javascript" src= "dwr/util.js"></script >
<script type="text/javascript" src= "dwr/engine.js"></script >
<script type="text/javascript" src= "dwr/interface/messagePush.js" ></script>
</head >
<body >
dwr接收<br />
<div id="content" style=" width: 200px ;height: 30px;border : 1px solid ; text-align: center ; padding: 5px;"></ div>
<script type="text/javascript" >
//這個方法用來啓動該頁面的ReverseAjax功能
dwr.engine.setActiveReverseAjax( true);
//設置在頁面關閉時,通知服務端銷燬會話
dwr.engine.setNotifyServerOnPageUnload( true);
//這個函數是提供給後臺推送的時候 調用的
function show(content){
$( "#content" ).text(content);
}
</script>
</body >
</html>
測試:
先打開receiver.jsp,後打開index.jsp輸入文本後發送,效果如圖: