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