如果想要兩個視窗內同步顯示兩支證券,那就得讓兩個瀏覽器之間能夠通訊,或者應該說兩個applet之間能夠通訊,java.applet包的AppletContext類提供了getApplet和getApplets方法以獲得其它applet的引用,使用這兩個方法,Applet能夠尋找到其他的Applet並調用它們的方法。不過這是以滿足如下安全條件為前提的: 所有Applet位於同一伺服器的同一目錄。 所有Applet運行在同一頁面且位於同一瀏覽器視窗內。 或許為Applet加上這些安全限制都有著很充分的理由,但第二個條件給我們實現帶有Applet到Applet通訊功能的多Applet介面帶來了限制。所有由於這些Applet位於不同的頁面,AppletContext中的Java API無法協助你完全實現我們的目標。 要實現跨頁面Applet到Applet通訊首先要滿足第一個條件,即如果兩個Applet具有相同的codebase,那麼即使它們運行在不同的瀏覽器視窗中,它們也將共用同一個運行時環境。所謂的codebase,我們可以粗略地把它看成Applet所在的伺服器目錄。共用運行時環境使得類的靜態域和結構能夠被所有的Applet執行個體訪問,因此,我們可以用這些靜態域和結構在不同的Applet之間傳遞資訊。 我們不僅可以把單一資料型別――比如整數、字元、字串儲存到這些靜態域,而且還可以儲存Applet執行個體本身的引用,這樣,其他的Applet就可以通過訪問這些靜態域得到該Applet執行個體的引用。假設有兩個Applet(AppletA.class和AppletB.class)位於不同的幀,但它們具有相同的codebase。 現在我們要從AppletA裡面訪問AppletB的公用方法。首先我們要在AppletB裡面把它自己的引用儲存到一個靜態公用域,如:
| public class AppletB { public static AppletB selfRef = null; public void init() { // 儲存當前執行個體的引用 selfRef = this; } ... } |
現在AppletA可以訪問AppletB的執行個體:
| public class AppletA{ AppletB theOtherApplet = null; public void callAppletB() { // 獲得靜態域的值,這個靜態域儲存了AppletB執行個體的引用 theOtherApplet = AppletB.selfRef; // 接下來就可以調用AppletB執行個體 的方法,例如: theOtherApplet.repaint(); } ...} |
這樣就實現了兩個Applet的通訊。由於不同的Applet共用運行時環境,因此即使這些Applet位於不同的頁面,這種方法也同樣有效。
不過應當注意的是,上面的代碼不能處理這種情況:在AppletB
沒有啟動之前就在AppletA
裡面調用callAppletB
方法。如果發生這種情況,則selfRef
的值將是null
,Applet
之間的通訊不能正常進行。 當然,我們還可以設計出更加通用的方法。我們可以建立一個類,這個類的用途就是在自己的待用資料結構中儲存其他Applet的引用。下面是一個參考實現AppletList。想要讓其他Applet訪問自己的公用方法的Applet執行個體首先要在AppletList中註冊。按照AppletContext.getApplet(string name)方法的處理模式,每個註冊的Applet都和一個字串相關聯。以後當其他Applet需要引用某個Applet執行個體時,這個字串就可以作為鍵(即Applet的標識)使用。 下面是Applet在AppletList中註冊的典型過程:
| public class AppletA { public void start(){ AppletList.register("Stock-trade-applet", this); ... } } |
其他Applet訪問登入Applet的過程如下:
| public class AppletB { public void run(){ AppletA tradeApplet =(AppletA) AppletList.getApplet("Stock-trade-applet"); ... } } |
當Applet結束運行時它必須從ApplietList取消註冊:
| public void stop(){ AppletList.remove("Stock-trade-applet"); ... } |
AppletList類的完整代碼如下:
| import java.util.*;import java.applet.Applet; public class AppletList { private static Hashtable applets = new Hashtable(); public static void register(String name, Applet applet) { applets.put(name,applet); } public static void remove(String name) { applets.remove(name); } public static Applet getApplet(String name) { return (Applet) applets.get(name); } public static Enumeration getApplets() { return applets.elements(); } public static int size() { return applets.size(); } } |
上述的辦法是對兩個不同的applet類來通訊,而我們的目標是讓同一個applet類在不同瀏覽器的同步,即在一支證券在一個瀏覽器中單步或自動回放,另一支證券要在另一個瀏覽器視窗中同步單步或自動回放,也就是無論點擊任何一個瀏覽器中的單步或自動按鈕,其餘的瀏覽器也要同步回放。因此,我們也不需要取其它applet的引用了,只要在單步或自動控制邏輯中加入調用從AppletList中取applet全集的函數getApplets,並遍曆這些applet,並迴圈調用單步或自動的控制邏輯就可以了,因為我們並不知道AppletList的HashTable中哪個是第一個開啟的視窗,哪個是第二個開啟的視窗,那就乾脆不管它是第幾個,只要HashTable中有幾個,那我們就調用這幾個applet的控制邏輯。下面是取applet的全集及迴圈執行的代碼:
| Enumeration appletList = AppletList.getApplets();while(appletList.hasMoreElements()){ OrderApplet tradeApplet = (OrderApplet)appletList.nextElement(); …… // 控制邏輯} |
但一定不能忘了,要在applet的stop方法中加入取消註冊的語句,否則如果已經開啟三個視窗,中途又關掉一個視窗,AppletList的HashTable中仍有三個applet的引用,與實際數量不符。
如前所述,參與通訊的Applet
必須具有相同的codebase
。此外,如果你啟動並執行是兩個不同的瀏覽器副本且Applet
分別運行於這兩個瀏覽器中,由於這些Applet
可能沒有共用運行時環境(這和瀏覽器版本、設定有關),因此它們可能不能進行通訊。然而,如果你是從同一個瀏覽器建立出新的瀏覽器視窗,那麼這個問題是不存在的。