DWR3.0框架入門(2) —— DWR的服務器推送
在開始本節內容之前,先來了解一下什么是服務器推送技術和DWR的推送方式。
1.服務器推送技術和DWR的推送方式
傳統模式的 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:這種方案實現的基礎是:一、 Flash 提供了 XMLSocket 類。二、 JavaScript 和 Flash 的緊密結合:在 JavaScript 可以直接調用 Flash 程序提供的接口。
優點:實時性好(消息延時小);性能好(能支持大量用戶)
缺點:因為 XMLSocket 沒有 HTTP 隧道功能, XMLSocket 類不能自動穿過防火牆;
因為是使用套接口,需要設置一個通信端口,防火牆、代理服務器也可能對非 HTTP 通道端口進行限制;
應用:網絡聊天室,網絡互動游戲。
5.java appet:在客戶端使用 Java Applet ,通過 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket 建立與服務器端的套接口連接,從而實現 “ 服務器推送 ” 。
DWR采用的是長連接機制。
1、長連接技術通過客戶端發出請求獲取服務器端數據的方式通常稱為"拉"技術,很形象說明客戶端在拉取服務器端數據,而有時候需要服務器端主動向客戶端"推"數據,比如監測聊天上線人數主動向上線發送消息,后台數據庫發生變化是主動更新所有客戶端展示。
2、Reverse Ajax實現服務器推技術DWR2.x的推技術也叫DWR Reverse Ajax(逆向Ajax)主要是在BS架構中,從服務器端向多個瀏覽器主動推數據的一種技術。DWR的逆向Ajax主要包括兩種模式:主動模式和被動模式。其中主動模式包括polling和comet兩種,被動模式只有piggyback這一種:
(1)piggyback方式,是默認的方式。如果后台有什么內容需要推送到前台,是要等到那個頁面進行下一次ajax請求的時候,將需要推送的內容附加在該次請求之后,傳回到頁面。只有等到下次請求頁面主動發起了,中間的變化內容才傳遞回頁面。
(2)comet方式當服務端建立和瀏覽器的連接,將頁面內容發送到瀏覽器之后,對應的連接並不關閉,只是暫時掛起。如果后面有什么新的內容需要推送到客戶端的時候直接通過前面掛起的連接再次傳送數據。服務器所能提供的連接數目是一定的,在大量的掛起的連接沒有關閉的情況下,可能造成新的連接請求不能接入,從而影響到服務質量。
(3)polling方式由瀏覽器定時向服務端發送ajax請求,詢問后台是否有什么內容需要推送,有的話就會由服務端返回推送內容。這種方式和我們直接在頁面通過定時器發送ajax請求,然后查詢后台是否有變化內容的實現是類似的。
2.ScriptSession的生命周期
客戶端每次請求(刷新)都會生成一個新的ScriptSession,當客戶端請求時或者客戶端退出時將會銷毀ScriptSession。
通過ScriptSession我們可以得到客戶端(瀏覽器)的腳本執行權。即我們可以直接調用瀏覽器的js代碼。
本節Demo實現的基本功能:
在上節( DWR3.0框架入門(1) —— 實現ajax )的代碼基礎上修改,實現將index.jsp輸入框中的推送文本顯示在其它打開的jsp頁面上
3.Demo修改的流程
1.修改MessagePush中的send方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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用來接收來自服務器的消息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<%@ 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輸入文本后發送,效果如圖: