java
applet包的AppletContext類包含如下兩個成員方法
getApplet和getApplets
使用這兩個方法
Applet能夠尋找到其他的Applet並調用它們的方法
不過這是以滿足如下安全條件為前提的
所有Applet位於同一服務器的同一目錄
所有Applet運行在同一頁面且位於同一浏覽器窗口內
或許為Applet加上這些安全限制都有著很充分的理由
但第二個條件給我們實現帶有Applet到Applet通信功能的多Applet界面帶來了限制
請設想如下情形
你剛好編寫完了一個用於股票交易的Applet
接下來想要為它做一個完善的幫助系統
這個幫助系統也是一個Applet
而且應該放到和股票交易Applet不同的另外一個幀裡
你作出這個決定的原因可能是出於網站整體結構的考慮
也可能是你想讓幫助系統總是處於顯示狀態
你還想讓幫助Applet能夠自動根據用戶的當前操作切換到相應的幫助條目(就象Microsoft Office幫助系統提供的那樣)
此外
你甚至還計劃著在幫助系統裡做一個向導
使它能夠在另外一個窗口中指導用戶如何完成股票交易Applet裡的各種任務
應當承認這種設想是非常美妙的
然而
由於這些Applet位於不同的頁面
AppletContext中的Java API無法幫助你完全實現這種設想——不過本文介紹的技術能夠
在介紹新的Applet到Applet通信方法之前
我們先要簡要地介紹一下getApplet和getApplets這兩個方法的用法
Applet能夠尋找到同一頁面的其他Applet
這既可以調用getApplet方法通過名字查找
也可以調用getApplets方法找出同一頁面內的所有Applet
這兩個方法都在調用成功時返回一個或多個Applet對象給調用者
調用者找到目標Applet對象之後
接著就可以調用它的公用方法
假設HTML頁面的代碼片斷如下
通過APPLET標記的name屬性
我們可以用如下代碼引用指定的Applet
Applet theOtherApplet = getApplet(
app
);
//調用該Applet的公用方法
theOtherApplet
anyMethod();
或者
我們也可以用下面的代碼提取頁面內的所有Applet
Enumeration allAppletsOnSamePage = getApplets();
while(allAppletsOnSamePage
hasMoreElements()) {
Applet appl = (Applet) allAppletsOnSamePage
nextElement();
// 調用Applet的公用方法
appl
anyMethod();
}
當發出調用的Applet提取到同一HTML頁面內的一個或多個Applet對象時
它就可以調用這些Applet對象的公用方法
遺憾的是
使用這種標准方法我們只能實現同一頁面內的Applet通信
但如果幸運的話
我們可以很方便地突破這一局限
實現跨頁面Applet到Applet通信基於這樣一個事實
即如果兩個Applet具有相同的codebase
那麼即使它們運行在不同的浏覽器窗口中
它們也將共享同一個運行時環境
所謂的codebase
我們可以粗略地把它看成Applet所在的服務器目錄
請參見本文後面參考資源中有關codebase示范的鏈接
共享運行時環境使得類的靜態域和結構能夠被所有的Applet實例訪問
因此
我們可以用這些靜態域和結構在不同的Applet之間傳遞信息
我們不僅可以把簡單數據類型——比如整數
字符
字符串存儲到這些靜態域
而且還可以存儲Applet實例本身的引用
這樣
其他的Applet就可以通過訪問這些靜態域得到該Applet實例的引用
這種方法非常復雜嗎?事實上
它並不復雜
下面我們來看一個簡單的例子
假設有兩個Applet(AppletA
class和AppletB
class)位於不同的幀
但它們具有相同的codebase
現在我們要從AppletA裡面訪問AppletB的公用方法
首先我們要在AppletB裡面把它自己的引用保存到一個靜態公用域
如
public class AppletB {
public static AppletB selfRef = null; // Initially zero
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();
: }
: }
請從本文後面下載exampleCode
zip了解更多有關如何應用AppletList類的信息
本方法的局限
如前所述
參與通信的Applet必須具有相同的codebase
此外
如果你運行的是兩個不同的浏覽器副本且Applet分別運行於這兩個浏覽器中
由於這些Applet可能沒有共享運行時環境(這和浏覽器版本
設置有關)
因此它們可能不能進行通信
然而
如果你是從同一個浏覽器創建出新的浏覽器窗口
那麼這個問題是不存在的
本文所介紹的技術已經順利通過好幾個平台和浏覽器版本的測試
但導致多個Applet擁有各自的運行時環境的配置還是存在的
順利通過測試的操作系統和浏覽器組合如下所示
小結
本文介紹了一種新的實現Applet到Applet通信的方法
這種方法在無法使用Java API的getApplet()方法時仍舊有效
掌握了這種方法
你就有更多的機會在Web網站或Intranet上使用Applet——用它來替換getApplets方法
或者補充getApplets方法的不足
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26802.html