首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

跨瀏覽器視窗 Java Applet 通訊實戰:靜態欄位共享執行個體引用

     編輯:Java 程式設計入門

前言:標準 API 的限制與突破

java.applet.AppletContext 提供 getApplet(String name) 與 getApplets() 尋找同頁面 Applet,但要求:同一伺服器、同一目錄、同一頁面、同一瀏覽器視窗。這對「主功能 Applet + 獨立說明/導覽視窗」等跨視窗架構構成阻礙。本文揭示利用 共享執行時期環境 (Codebase 相同) 並透過 static 欄位傳遞執行個體引用的實戰技巧。

核心原理

  • 相同 codebase (伺服器目錄) 的 Applet,即便載入於不同 HTML 頁面/框架/視窗,共享同一個 JVM 類別載入器命名空間。
  • static 欄位屬於類別,而非執行個體,因此對所有 Applet 執行個體可見。
  • Applet A 將 this 存入 Applet B 類別的 static 欄位,Applet C 即可讀取並呼叫 B 的公用方法。

實作步驟與程式碼

步驟 1:目標 Applet (AppletB) 暴露自身引用

public class AppletB extends Applet {
    // 靜態公用欄位,保存目前執行個體引用
    public static AppletB selfRef = null;

    public void init() {
        selfRef = this; // 初始化時註冊自己
    }

    // 業務方法:供其他 Applet 呼叫
    public void showHelpTopic(String topic) {
        // 切換說明內容、高亮顯示等
        repaint();
    }

    public void destroy() {
        selfRef = null; // 釋放引用,避免記憶體洩漏
    }
}

步驟 2:呼叫端 Applet (AppletA) 取得引用並互動

public class AppletA extends Applet {
    private AppletB helpApplet = null;

    private void ensureHelpApplet() {
        if (helpApplet == null) {
            helpApplet = AppletB.selfRef; // 直接讀取靜態欄位
        }
    }

    public void onUserAction(String context) {
        ensureHelpApplet();
        if (helpApplet != null) {
            helpApplet.showHelpTopic(context); // 跨視窗呼叫!
        } else {
            showStatus("說明視窗尚未載入,請稍候...");
        }
    }
}

HTML 部署範例

<!-- 主功能頁面 -->
<APPLET code="AppletA.class" codebase="/applets/" width="600" height="400"></APPLET>

<!-- 獨立說明視窗 (以 JavaScript 開啟新視窗) -->
<script>
window.open('/help/help.html', 'helpWin', 'width=400,height=500');
</script>

<!-- help.html -->
<APPLET code="AppletB.class" codebase="/applets/" width="400" height="500"></APPLET>

關鍵:兩個 <APPLET> 標籤的 codebase="/applets/" 完全相同。

進階議題與最佳實踐

1. 生命週期同步

  • 呼叫前必須檢查 null,因視窗載入順序不定。
  • 監聽 AppletContext 事件或定時輪詢確認對方就緒。
  • 在 destroy() 清除 static 引用,防止記憶體洩漏與殭屍引用。

2. 執行緒安全

跨 Applet 呼叫發生在 AWT 事件派發執行緒 (EDT) 或自訂執行緒。若目標方法操作 UI 元件,必須用 SwingUtilities.invokeLater() 或 EventQueue.invokeLater() 佇列至 EDT:

public void showHelpTopic(final String topic) {
    EventQueue.invokeLater(() -> {
        // 安全地更新 UI
        textArea.setText(topic);
        repaint();
    });
}

3. 多實例情境

若同一頁面可能載入多個 AppletB 實例,單一 static 欄位不足。改用 static Map registry,鍵值可為視窗 ID、Session ID 或隨機 UUID,AppletA 需知曉對應鍵值 (可透過 JavaScript 協商傳遞)。

4. 安全性考量

  • 僅暴露必要業務介面 (介面隔離原則),勿直接暴露 Applet 子類別。
  • 簽名 Applet + 安全策略限制呼叫者來源 (CodeSource 驗證)。
  • 現代替代方案:共享 Web Worker / Broadcast Channel / localStorage + postMessage 實現無插件跨視窗通訊。

結語

靜態欄位共享引用是 Java Applet 時代突破「同頁面」限制的經典模式,其本質是利用共享類別載入器命名空間實現進程內服務定位。這一思想在現代微服務架構中以「服務註冊與發現」(Consul, Eureka, Nacos)、「模組熱插拔」(OSGi, JPMS) 等形式延續演進。理解其核心機制,有助於掌握分散式系統服務治理的本質。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved