让不同页面的applet之间能够通信

原创 2001年06月26日 10:12:00
Java 技巧 101:applet 间通信的替代方法
了解如何让 applet 跨框架和浏览器窗口彼此通信

作者 Tobias Hill
摘要
您可能认为能让 applet 彼此通信的唯一选择就是使用 getApplet。不幸的是,getApplet 方法仅返回与发出调用的 applet 在同一个 HTML 页面上的 applet,这样就限制了您通过 applet 间的通信构建有趣界面的方式。这篇技巧说明的替代方法能使处于不同框架甚至不同浏览器窗口中的 applet 彼此调用对方的方法。
java.applet 包中的 AppletContext 类包含两个成员方法,即 getAppletgetApplets。通过使用这两个方法,一个 applet 就可以找到其他 applet 并调用它们的方法。要这样做必须满足下面的安全要求:

  • 这些 applet 来自同一个服务器上的同一个目录中。

  • 这些 applet 运行于同一个浏览器窗口中的同一个页面上。

这样设计安全限制可能有很好的原因;但是,后一个要求限制了利用 applet 间的通信制作有趣的多 applet 界面的方式。

试考虑这样一种情况:

您刚编好一个很好的股票市场交易 applet,并决定为它编写一个良好的帮助系统。您希望帮助系统也是一个 applet,并希望将它与股票市场交易 applet 在不同的浏览器框架中运行。您作出这个决定可能是出于网站结构方面的考虑,也可能是出于始终显示帮助系统的需要。另外,您希望使帮助系统根据用户当前在股票交易 applet 中进行的操作转至正确的信息/指导(就像 Microsoft Office 套件中的“回形针”一样)。您甚至计划在帮助系统中编制向导,这些向导可远程指出问题,并可远程执行股票市场交易 applet 中的任务。

这一方案中体现的思想很不错。但是,因为这两个 applet 处于不同的页面上,所以 AppletContext 中的 Java API 无法帮助您实现这个想法 -- 但这篇技巧可以帮助您。

使用 AppletContext API
在说明 applet 间通信的替代机制前,我将首先简要说明一下 getAppletgetApplets 这两个方法是如何工作的。一个 applet 通过使用 getApplet 方法可以按名称找到同一个 HMTL 页面中的另一个 applet,而通过使用 getApplets 方法可以找到同一个页面上的所有 applet。这两个方法如果成功执行,则会向调用者返回一个或多个 Applet 对象。调用者一旦找到一个 Applet 对象,它就可能调用这个 Applet 的公用方法。

假定有下面这样一段 HTML 代码:

    <applet code="Applet1" width="400" height="100" name="app1">
    </applet>
    <br>
    <applet code="Applet2" width="400" height="100" name="app2">
    </applet>
    <br>

通过使用 applet 标记中的 name 属性,您就可以用下面的方式引用一个特定的 applet:

    Applet theOtherApplet = getApplet("app1");
    theOtherApplet.anyMethod(); //调用任一个公用方法

或者,您也可以用以下的代码来检索这个页面上的所有 applet:

    Enumeration allAppletsOnSamePage = getApplets();
    while(allAppletsOnSamePage.hasMoreElements()) {
        Applet appl = (Applet) allAppletsOnSamePage.nextElement();
        appl.anyMethod(); //调用任一个公用方法
    }

当发出调用的 applet 在它所在的同一个 HTML 页面上检索到一个或几个 applet 之后,它就可以调用这些 applet 的公用方法。

使用静态数据结构
不幸的是,如果使用标准方法,则只能与同一个 HTML 页面中的 applet 通信。幸运的是,您很容易就可以避开这个限制。使 applet 间跨页面通信的方法基于这样一个事实,即如果两个 applet 的 codebase 相同,则即使它们是在不同的浏览器窗口中被加载的,它们也共享同一个运行时环境。粗略地说,codebase 就是从中加载 applet 的那个目录。请参阅文后的参考资源,其中有一个链接指向有关 codebase 的一篇教程。

由于运行时环境是共享的,因此所有 applet 实例都可以访问静态域和静态结构,这样这些静态域和结构就可用来在不同 applet 之间传递信息。

applet 不仅可以存储诸如整数、字符和字符串这样的简单数据类型,而且每个 applet 都可以将其自身(实例)的一个引用存储在一个静态域(可能在它自己的类中)中。任何 applet 都可以访问这个域,从而获得指向这个实例的引用。

这听起来复杂吗?不,一点也不复杂。我首先举一个简单的例子。假定您的一个 applet (AppletA.class) 在一个框架中,而另一个 applet (AppletB.class) 在另一个框架中,而且这两个 applet 都是从同一个 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;

            // 此后就可以调用实例方法了,
            // 如下所示...
            theOtherApplet.repaint();
        }
        ...
    }

这就是我们所要做的全部工作。因为运行时环境是由不同的 applet 共享的,所以即便 applet 不在同一个页面上,这个方法同样奏效。

值得注意的一点是,上面的代码并没有处理在启动 AppletB 之前就调用 AppletA 中的 callAppletB 方法的情况。如果发生这种情况,则 selfRef 将是 null,这样不能进行任何通信。

一种更通用的方法
当然,还有一种更通用的方法。您可以创建这样一个类,创建它的唯一目的就是在静态数据结构中存储 applet 的引用。稍后您将看到的 AppletList 类就属于这种情况。希望其他 applet 访问自己的公用方法的 applet 实例通过 AppletList 将自己注册。按照 AppletContext.getApplet(string name) 中的模式,每个注册项都与一个字符串相关联。当一个 applet 调用某个 applet 的引用时,这个字符串就起关键字的作用。

通常,applet 是按下面的方式注册的:

    public class AppletA {
        public void start() {
            AppletList.register("Stock-trade-applet", this);
            ...
        }
    }

另一个 applet 获取对它的访问权:

    public class AppletB {
        public void run() {
            AppletA tradeApplet =
                (AppletA) AppletList.getApplet("Stock-trade-applet");
            ...
        }
    }

当该 applet 停止运行时,您必须紧记在 AppletList 中撤销注册:

    public void stop() {
        AppletList.remove("Stock-trade-applet");
        ...
    }

AppletList 类的完整源代码如下所示:

0: import java.util.*;
1: import java.applet.Applet;
2:
3: public class AppletList {
4: private static Hashtable applets = new Hashtable();
5:
6: public static void register(String name, Applet applet) {
7: applets.put(name,applet);
8: }
9:
10: public static void remove(String name) {
11: applets.remove(name);
12: }
13:
14: public static Applet getApplet(String name) {
15: return (Applet) applets.get(name);
16: }
17:
18: public static Enumeration getApplets() {
19: return applets.elements();
20: }
21:
22: public static int size() {
23: return applets.size();
24: }
25: }

要获得说明如何使用这个类的示例,请在参考资源中下载 exampleCode.zip。

局限性
正如我在前面提到的那样,必须从同一个 codebase 中加载这些 applet。此外,如果浏览器的两个不同副本正在运行,并且 applet 被加载到每个副本中,则 applet 可能无法彼此通信(取决于浏览器的版本和设置),因为它们可能不再共享同一个运行时环境。但是,如果是浏览器本身衍生出新的浏览器窗口,则没有任何问题。

该技巧已在几个平台和几个浏览器版本中通过测试,但在某些配置中每个 applet 的运行时环境可能是独立的。该技巧已在下面的操作系统和浏览器组合中通过测试:

Windows 2000: Internet Explorer 5.0,Internet Explorer 5.5,Netscape Navigator 4.72,Opera 4.01
Windows 98: Internet Explorer 4.72,Internet Explorer 5.0,Netscape Navigator 4.02
Mac OS 9: Internet Explorer 4.5,Netscape Navigator 4.5
Red Hat 6.2: Netscape Navigator 4.73

小结
这篇技巧说明了能使 applet 彼此通信的一种替代方法。这种方法以 Java API 的 getApplet() 方法不支持的方式工作。这篇技巧中介绍的知识增大了将 applet 作为网站或内部网的一部分的可能性 -- 可以用它替代或补充 getApplets 方法。

  作者简介
Tobias HillCiterus 的创办者之一,该公司以瑞典为基地,致力于在 Java 平台上构建因特网、内部网和外部网系统。Hill 从 1996 年开始用 Java 编程,参与了许多项目,从为自主控制的机器人编程到开发在线焰火明信片制作程序等等。


参考资源

不同窗口之间传递参数html版

程序实现网页弹出页面输入值并返回父窗口:方便大家测试。测试window.showModalDialog()方法传递值的子页面和window.open()方法传递值的子页面1 TestTransferV...
  • longronglin
  • longronglin
  • 2007年05月12日 23:13
  • 2300

不同VLAN之间互相通信

前话我们经常到机房上课,想必对机房后面那层叠的跟DVD一样的机器有印象吧,那些就是交换机。交换机作用是什么?我这里度娘一下: 交换机(Switch)意为“开关”是一种用于电(光)信号转发的网络设备...
  • pwc1996
  • pwc1996
  • 2016年01月26日 18:47
  • 11442

不同VLAN之间通信的原理

在划分VLAN后,不同VLAN之间不能直接进行二层通信。如果要实现VLAN间通信,可以采取以下3种方案之一。 1.三层VLANIF接口方案 这是一种通过计算机网络体系结构中第三层(网络层)来实现V...
  • u013903472
  • u013903472
  • 2015年07月19日 10:33
  • 7630

CISCO 不同VLAN之间相互通信的两种方式

CISCO 不同VLAN之间相互通信的两种方式 不同VLAN之间相互通信的两种方式(单臂路由、三层交换) 试验环境:东郊二楼第三机房 试验设备:Catalyst 2950-24(SW3) ...
  • lingxiao1126
  • lingxiao1126
  • 2012年07月05日 23:16
  • 3044

即时通信与浏览器多TAB通信

摘要 浏览器与服务器端的即时通信技术解决了在线聊天等产品中涉及到的复杂网络环境下的问题;采用多tab通信技术来处理现代浏览器的跨页面通信,分析特定疑难问题的技术解决方案。 TAG 即时通信,多...
  • luqin1988
  • luqin1988
  • 2012年11月29日 23:09
  • 1145

同网段和不同网段设备通信原理详解

在当今的以太网络通信中,在IP数据包中有两个必不可少的地址,那就是IP地址和网卡地址(即MAC地址),在数据包中,无论是IP地址还是MAC地址,都有源地址和目标地址,因为通信是双方的,所以就必须同时拥...
  • tao546377318
  • tao546377318
  • 2015年12月15日 11:50
  • 6346

两不同程序之间通讯

其实两个java项目之间的通信还是使用HTTP的请求。主要有两种方式: ①使用apache的HttpClient方式。 ②使用JDK自带的java.NET包下的HttpURLConnection方...
  • mengyong1108
  • mengyong1108
  • 2017年08月12日 09:54
  • 120

HTML5之窗口间通信

准备工作:虚拟主机相关配置     同域下窗口间通信的二种方式:1.iframe  2 window.open   同域下的窗口通信 方式一:iframe 1.    iframe....
  • u013267266
  • u013267266
  • 2016年06月25日 19:37
  • 3171

ngularJs项目实战05: 不同controller作用域之间通信的方式

不同controller作用域之间通信的方式详解
  • lai_xu
  • lai_xu
  • 2015年11月03日 10:42
  • 2600

不同主机间的 Docker 容器相互通信

Ubuntu14.0.4为例 宿主主机: ip :192.168.220.131   (ifconfig查看) gateway:192.168.220.2  (netstat -rn  desti...
  • sunshingheavy
  • sunshingheavy
  • 2016年12月27日 13:32
  • 1143
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:让不同页面的applet之间能够通信
举报原因:
原因补充:

(最多只允许输入30个字)