用推送技術(shù)動(dòng)態(tài)更新頁面內(nèi)容
一、什么是動(dòng)態(tài)內(nèi)容 大多數(shù)熱門Web網(wǎng)站都從在線廣告業(yè)務(wù)獲利。Web頁面中的廣告空間是有限的,為了讓廣告投資物有所值,廣告客戶不僅必須在很小的廣告空間內(nèi)塞入大量的信息,而且還要保證廣告能夠吸引用戶的注意力。在當(dāng)前的大多數(shù)網(wǎng)站上,放入Web頁面的橫幅廣告一般由服務(wù)器在構(gòu)造頁面的同時(shí)生成,我們無法把新的廣告動(dòng)態(tài)地插入到已經(jīng)發(fā)送出去的頁面。 如果要顯示新的廣告,的辦法是重新刷新頁面。我們可以用編程的方法刷新頁面,例如:
使用瀏覽器窗口對象的setTimeOut函數(shù)定期地刷新頁面。但是,用這種方法刷新廣告時(shí),用戶會(huì)很明顯地感到頁面刷新過程;同時(shí),要確定一個(gè)合適的刷新頻率也很困難。 把頁面的過期時(shí)間設(shè)置為數(shù)秒時(shí)間,使得無論何時(shí)輸入焦點(diǎn)轉(zhuǎn)到該頁面(即瀏覽器被)時(shí),瀏覽器會(huì)重新下載該頁面。 一些大型網(wǎng)站,如yahoo.com和msn.com,都已經(jīng)采用了這些技術(shù)。這兩種方法都有各自的優(yōu)點(diǎn)和缺點(diǎn)。在只使用Java的情況下,我們完全可以通過網(wǎng)絡(luò)編程和一些界面編程工作實(shí)現(xiàn)橫幅廣告的刷新系統(tǒng),但必須解決下載時(shí)間過長和刷新延遲的問題。
二、用Java實(shí)現(xiàn)內(nèi)容推送 結(jié)合JavaScript幀間通信和一個(gè)管理網(wǎng)絡(luò)通信的Java Applet,我們能夠用推送技術(shù)解決這個(gè)問題。在這樣一個(gè)系統(tǒng)中,Java Applet的任務(wù)是連接服務(wù)器并監(jiān)聽內(nèi)容更新。一旦接收到了新的內(nèi)容,Applet構(gòu)造出顯示這些新內(nèi)容的HTML代碼,調(diào)用一個(gè)JavaScript函數(shù)并把包含新內(nèi)容的HTML傳遞給JavaScript函數(shù)。JavaScript函數(shù)運(yùn)用DHTML和DOM技術(shù),把頁面中一個(gè)標(biāo)記的內(nèi)容用參數(shù)中傳入的新內(nèi)容替換。由于瀏覽器的限制,Applet所打開的Socket端口只能連接到下載該Applet的服務(wù)器。
Web服務(wù)器只在80端口監(jiān)聽連接請求。因此,除了Web服務(wù)器之外,我們還需要一個(gè)接受Applet的Socket連接請求的網(wǎng)絡(luò)應(yīng)用服務(wù)。這個(gè)網(wǎng)絡(luò)應(yīng)用服務(wù)定時(shí)地查詢數(shù)據(jù)庫,把改動(dòng)數(shù)據(jù)發(fā)布(推送)到所有已經(jīng)連接的Applet。由于運(yùn)用了隱藏幀和JavaScript的幀間通信功能,我們能夠從用戶面前隱藏大多數(shù)JavaScript邏輯。
在這整個(gè)處理過程中,最困難的任務(wù)是Java Applet與JavaScript代碼之間的通信。Netscape提供了一個(gè)稱為netscape.javascript.JSObject的類。要使用這個(gè)對象,請加入一個(gè)包含特殊“MAYSCRIPT”屬性的Applet標(biāo)記:
JSObject的方法允許Applet與文檔對象交互以及調(diào)用JavaScript命令。例如,把下面的代碼放入Applet,我們能夠訪問窗口對象:
import netscape.javascript.*; public class MyApplet extends java.applet.Applet{ private JSObject mainwin; public void init(){ mainwin = JSObject.getWindow(this); } }
獲得JSObject引用后,我們能夠訪問文檔窗口對象,并通過JSObject的eval()方法調(diào)用JavaScript函數(shù)。
三、用DHTML更新頁面 在把來自Applet的新內(nèi)容寫入文檔時(shí),為了不影響原來已經(jīng)存在的內(nèi)容,我們可以使用HTML的標(biāo)記。這個(gè)標(biāo)記在IE和Netscape中是不同的。
對于IE以及Netscape 6,這個(gè)HTML標(biāo)記是:
// 所有要更新的內(nèi)容必須用id標(biāo)識
對于Netscape 4.x版本,這個(gè)HTML標(biāo)記是:
雖然我們可以通過引用適當(dāng)?shù)腎D,從Applet直接更新HTML內(nèi)容,但為了清楚起見,我們將把更新HTML代碼的程序邏輯放入JavaScript函數(shù)。下面的JavaScript代碼把瀏覽器的類型保存到ie變量:
applnname=navigator.appName; if(applnname=="Microsoft Internet Explorer") { ie=true; } else { ie=false; }
Applet從新數(shù)據(jù)構(gòu)造出HTML代碼,把它保存到JavaScript變量content,然后調(diào)用assignData()方法。內(nèi)容數(shù)據(jù)可以是從純HTML到XML到二進(jìn)制數(shù)據(jù)的任何東西。
// 根據(jù)瀏覽器類型調(diào)用合適的方法 function assignData() { if(ie) {explore();} else {navig(); } }
如果瀏覽器是IE或者Netscape 6,Applet調(diào)用explore()方法:
//content是一個(gè)javascript變量,它以HTML格式描述了需要 //顯示的新數(shù)據(jù) function explore() { iexplorer.innerHTML=content; }
如果瀏覽器是Netscape 4.0或者更高版本,Applet調(diào)用navig()方法:
function navig() { document.netscapev.document.write(““ + content + ““); document.netscapev.document.close(); }
四、通信過程 在服務(wù)器端,一個(gè)ImageAppliation.java類的實(shí)例響應(yīng)Socket連接請求,并為每一個(gè)新的連接請求創(chuàng)建一個(gè)新的線程。為了簡化代碼,每一個(gè)線程只檢查數(shù)據(jù)文件是否改變。如果數(shù)據(jù)文件已經(jīng)改變,則線程讀取文件內(nèi)容,并把新的數(shù)據(jù)發(fā)送給已經(jīng)連接的Applet(示例應(yīng)用把整個(gè)文件發(fā)送給Applet)。
在客戶端,一個(gè)隱藏幀包含了ImageApplet.java這個(gè)Applet,因此用瀏覽器的查看HTML源代碼功能是無法看到Applet標(biāo)記的。Applet實(shí)現(xiàn)了連接服務(wù)器(下載該Applet的源服務(wù)器)的功能,并實(shí)現(xiàn)了一個(gè)簡單的通信協(xié)議。建立與服務(wù)器的連接之后,Applet接收來自服務(wù)器的數(shù)據(jù),構(gòu)造出HTML代碼,并調(diào)用JavaScript函數(shù)把數(shù)據(jù)傳入文檔:
public void upDateHTML(String str){ //data是表單的名字, //quote是一個(gè)JavaScript變量 //str是新構(gòu)造出來的HTML代碼 mainwin.eval("document.data.quote.value=“" + str + "“"); mainwin.eval("javascript:assignData()"); return; }
netscape.javascript.JSObject完成Applet到JavaScript的通信,不同版本的客戶端瀏覽器需要不同的版本。你可以下載得到為Netscape提供的壓縮類文件java40.jar。IE已經(jīng)帶有JSObject類,但有點(diǎn)難找。你可以搜索$windows$\Java\Packages目錄尋找包含JSObject類的ZIP文件。
服務(wù)器把ImageArrayElement.java類的實(shí)例通過toString()方法串行化成為字符串發(fā)送給Applet。服務(wù)器從數(shù)據(jù)文件構(gòu)造出各個(gè)對象,調(diào)用toString()方法,連接得到代表所有對象的字符串,發(fā)送結(jié)果字符串。而在另一端,Applet接收并解析這個(gè)字符串,重新構(gòu)造出各個(gè)ImageArrayElement對象。這里之所以用一個(gè)長字符串的形式發(fā)送數(shù)據(jù),是因?yàn)檫@種方法只需要很簡單的處理過程,使得用戶能夠以接近實(shí)時(shí)的速度立即得知數(shù)據(jù)的變化;但是,我們也可以用另外一種方法,即以向量的形式發(fā)送對象。
在一個(gè)正式運(yùn)行的應(yīng)用中,你一般應(yīng)該讓新數(shù)據(jù)插入當(dāng)前頁面的過程透明。但在示例應(yīng)用中,為了讓程序運(yùn)行過程更加直觀,它將在新內(nèi)容到達(dá)的時(shí)候提示用戶。
推送技術(shù)最主要的優(yōu)點(diǎn)是應(yīng)用服務(wù)器只把那些改變的數(shù)據(jù)發(fā)送到網(wǎng)絡(luò),從而使得延遲減到了最少。由于這個(gè)Applet負(fù)責(zé)完成的工作非常少(不涉及用戶界面,這部分工作由瀏覽器負(fù)責(zé)),所以Applet體積很小,裝載速度非?。
五、如何運(yùn)行本文實(shí)例 要測試本文示例應(yīng)用,你的機(jī)器上必須安裝有Web服務(wù)器和JDK 1.7或更高版本。
安裝要點(diǎn):
解開ZIP壓縮文件并安裝到Web服務(wù)器默認(rèn)根目錄。 對于IIS服務(wù)器,默認(rèn)根目錄是Inetput\wwwroot 對于jsdk2.1所帶的免費(fèi)服務(wù)器,默認(rèn)目錄是\webpages 解開壓縮文件之后,所有文件都將安裝到/exp/目錄。 把下面幾行代碼加入默認(rèn)頁面。每一種服務(wù)器都有自己的默認(rèn)頁面,IIS的默認(rèn)頁面是“default.htm”,請參見Web服務(wù)器文檔了解具體說明:
Java based dynamic Ad-Banner
運(yùn)行應(yīng)用的步驟:
打開一個(gè)DOS窗口,進(jìn)入/exp,執(zhí)行“java ImageApplication”。系統(tǒng)將顯示“Server started listening at port 6011”。注意確保classpath環(huán)境變量指向了當(dāng)前工作目錄。 啟動(dòng)Web服務(wù)器。 打開瀏覽器輸入下面的URL:http://localhost:8080。該URL將打開Web服務(wù)器的默認(rèn)頁面,它應(yīng)該有一個(gè)“Java based dynamic Ad-Banner”鏈接。點(diǎn)擊這個(gè)鏈接啟動(dòng)了本文的示例應(yīng)用。 用Notepad打開“/exp/images.txt”文件,復(fù)制并粘貼一行內(nèi)容,保存文件。你可以立即看到系統(tǒng)顯示一個(gè)JavaScript窗口提示內(nèi)容更新。關(guān)閉JavaScript窗口,頁面將顯示新的內(nèi)容。 請從這里下載本文實(shí)例的完整代碼,411 KBhttp://www.89cn.com/down/pushweb.zip