电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

如何实现Applet之间跨浏览器窗口的通信


发布日期:2021/8/9
 

javaapplet包的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的公用方法

theOtherAppletanyMethod();

或者我们也可以用下面的代码提取页面内的所有Applet

Enumeration allAppletsOnSamePage = getApplets();

while(allAppletsOnSamePagehasMoreElements()) {

Applet appl = (Applet) allAppletsOnSamePagenextElement();

// 调用Applet的公用方法

applanyMethod();

}

当发出调用的Applet提取到同一HTML页面内的一个或多个Applet对象时它就可以调用这些Applet对象的公用方法

遗憾的是使用这种标准方法我们只能实现同一页面内的Applet通信但如果幸运的话我们可以很方便地突破这一局限实现跨页面Applet到Applet通信基于这样一个事实即如果两个Applet具有相同的codebase那么即使它们运行在不同的浏览器窗口中它们也将共享同一个运行时环境所谓的codebase我们可以粗略地把它看成Applet所在的服务器目录请参见本文后面参考资源中有关codebase示范的链接

共享运行时环境使得类的静态域和结构能够被所有的Applet实例访问因此我们可以用这些静态域和结构在不同的Applet之间传递信息

我们不仅可以把简单数据类型——比如整数字符字符串存储到这些静态域而且还可以存储Applet实例本身的引用这样其他的Applet就可以通过访问这些静态域得到该Applet实例的引用

这种方法非常复杂吗?事实上它并不复杂下面我们来看一个简单的例子假设有两个Applet(AppletAclass和AppletBclass)位于不同的帧但它们具有相同的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 = AppletBselfRef;

// 接下来就可以调用AppletB实例

// 的方法例如

theOtherAppletrepaint();

}

}

这样就实现了两个Applet的通信由于不同的Applet共享运行时环境因此即使这些Applet位于不同的页面这种方法也同样有效

不过应当注意的是上面的代码不能处理这种情况在AppletB没有启动之前就在AppletA里面调用callAppletB方法如果发生这种情况则selfRef的值将是nullApplet之间的通信不能正常进行

当然我们还可以设计出更加通用的方法我们可以创建一个类这个类的唯一用途就是在自己的静态数据结构中保存其他Applet的引用下面是一个参考实现AppletList想要让其他Applet访问自己的公用方法的Applet实例首先要在AppletList中注册按照AppletContextgetApplet(string name)方法的处理模式每个注册的Applet都和一个字符串相关联以后当其他Applet需要引用某个Applet实例时这个字符串就可以作为键(即Applet的标识)使用

下面是Applet在AppletList中注册的典型过程

public class AppletA {

public void start() {

AppletListregister(Stocktradeapplet this);

}

}

其他Applet访问已注册Applet的过程如下

public class AppletB {

public void run() {

AppletA tradeApplet =

(AppletA) AppletListgetApplet(Stocktradeapplet);

}

}

当Applet结束运行时它必须从ApplietList取消注册

public void stop() {

AppletListremove(Stocktradeapplet);

}

AppletList类的完整代码如下

: import javautil*;

: import javaappletApplet;

:

: public class AppletList {

: private static Hashtable applets = new Hashtable();

:

: public static void register(String name Applet applet) {

: appletsput(nameapplet);

: }

:

: public static void remove(String name) {

: appletsremove(name);

: }

:

: public static Applet getApplet(String name) {

: return (Applet) appletsget(name);

: }

:

: public static Enumeration getApplets() {

: return appletselements();

: }

:

: public static int size() {

: return appletssize();

: }

: }

请从本文后面下载exampleCodezip了解更多有关如何应用AppletList类的信息

本方法的局限

如前所述参与通信的Applet必须具有相同的codebase此外如果你运行的是两个不同的浏览器副本且Applet分别运行于这两个浏览器中由于这些Applet可能没有共享运行时环境(这和浏览器版本设置有关)因此它们可能不能进行通信然而如果你是从同一个浏览器创建出新的浏览器窗口那么这个问题是不存在的

本文所介绍的技术已经顺利通过好几个平台和浏览器版本的测试但导致多个Applet拥有各自的运行时环境的配置还是存在的顺利通过测试的操作系统和浏览器组合如下所示

小结

本文介绍了一种新的实现Applet到Applet通信的方法这种方法在无法使用Java API的getApplet()方法时仍旧有效掌握了这种方法你就有更多的机会在Web网站或Intranet上使用Applet——用它来替换getApplets方法或者补充getApplets方法的不足

上一篇:交通灯管理系统

下一篇:工作流引擎Shark中调用外部程序的方法