如何在浏览器和 Java Web Start 小程序之间进行通信

How to communicate between browser and Java Web Start applet

现状

我们目前使用一个小程序来执行一些操作,之后它会重定向当前页面。在其核心中,您可以看到如下小程序:

public class ExampleApplet extends Applet {
    @Override
    public void init() {
        Button redirect = new Button("Redirect");
        this.add(redirect);
        final String target = this.getParameter("targetPage");
        redirect.addActionListener((ActionEvent e) -> {
            try {
                getAppletContext().showDocument(new URL(target), "_parent");
            } catch (MalformedURLException ex) {}
        });
    }
}

以最简单的方式调用小程序:

<applet code="com.example.applet.ExampleApplet.class" archive="${appletUrl}" width="100" height="30">
    <param name="targetPage" value="http://localhost:8080/applet/"/>
</applet><br/><br/>

其中 ${appletUrl} returns 小程序 JAR 的位置。

所以小程序只不过是一个调用getAppletContext().showDocument(new URL(target), "_parent");刷新当前页面的简单按钮。这已经正确地完成了很长一段时间的工作。问题来了。

迁移

正如许多人所知,Chrome 不支持 Applet。由于 IEFireFox 仍然支持他们,因此搁置了一段时间。 2016年底,他们也将不再支持他们。所以我们决定使用 JWSJNLP.

迁移小程序

迁移这个简单的重定向按钮示例将提供以下 html 片段和 JNLP 文件:

<a href="${jnlpUrl}">Launch JNLP</a>

${jnlpUrl} returns JNLP 文件的位置是:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="http://localhost:8080/applet/assets/1.0-SNAPSHOT-DEV/app/assets/" href="jnlp/example.jnlp">
    <security>
        <all-permissions/>
    </security>
    <resources>
        <j2se version="1.5+" initial-heap-size="32m" max-heap-size="128m" />
        <property name="jnlp.versionEnabled" value="false"/>
        <jar href="applets/ExampleApplet.jar" main="true"/>
    </resources>
    <applet-desc name="code" main-class="com.example.applet.ExampleApplet.class" width="30" height="30" >
        <param name="targetPage" value="http://localhost:8080/applet/"/>
    </applet-desc>
</jnlp>

到目前为止一切顺利,同一个小程序成功部署为 JWS 应用程序。允许从任何浏览器使用它,因为它是在它之外执行的。这也是一个问题。

问题

getAppletContext().showDocument(new URL(target), "_parent"); 仍然进行重定向,但它使用 migration documentation.

中所述的默认浏览器

For AppletContext.showDocument(URL url, String target), the target argument will be ignored by Java Web Start technology.

Similar to AppletContext.showDocument, Java Web Start applications are capabile of showing an HTML page using the system's default web browser by using the BasicService.showDocument API.

因此,如果我的默认浏览器是 FireFox,但我恰好在 IE/Chrome 中浏览到此 JWS-enabled applet,则会在 FireFox 中打开一个新选项卡。这是一个问题,因为我在原始浏览器中存储了信息(例如登录)!

调查结果

由于应用程序 运行 在浏览器之外,我在考虑与原始浏览器通信的可能性时遇到了问题。我无法使用 JavaScript,因为它不会在浏览器中使用 运行。我无法真正定义一种独立于系统的方式来在原始浏览器中打开选项卡。我也想到了 WebSockets,因为它们可以允许直接通信,但从我读到的内容来看,它是相当高级的,需要一个服务器,而不是一个简单的小程序。

当小程序打开一个新的window时,是否有可能在原始浏览器之间进行通信(例如websockets和参数)或将会话从一个浏览器传递到另一个浏览器window?

我找到了可行的解决方案。

由于 applet 失去了与浏览器及其会话的所有连接,另一种提供通信的方法是 WebSocketsComet。在我的例子中,我使用 CometAtmosphere framework and a Tapestry-Atmosphere 实现,因为 Tapestry 是我正在使用的视图框架。

在不深入 Tapestry 实施的情况下,我做了以下工作:

  • 在客户端浏览器上设置一个 Topic,它将以典型的 publish/subscribe 方式收听广播消息。
  • 将当前浏览用户唯一的 Topic 的 ID 提供给 Applet,以及 URL 以向其发送请求。使用 Topic ID 作为 url.
  • 的请求参数
  • 服务器端我有接收 Topic 作为请求参数的请求端点。使用此参数,它向主题发送广播(可能为空)。
  • 客户端Topic收到通知并自行执行事件。该事件是重新呈现页面的特定内容。

因为它使用 Comet(但也可以使用 WebSockets),它直接在浏览器中发生。每个浏览器实际上都订阅了 Topic,但这里只有一个。

使从小程序的简单请求更新页面成为可能。该小程序仅将行 getAppletContext().showDocument(new URL(target), "_parent"); 更改为 new URL(target).openConnection().getInputStream();target 是包含请求参数的 URL。

这是对旧线程的回答。我们在我们的环境中面临着类似的情况。这是它的地址。

Can an Applet that uses JavaScript to communicate with web server be migrated to JWS?

解决方案与 James 描述的类似。我们在服务器端维护了一个以 uid 为键的请求哈希图。然后 Web 应用程序会长时间轮询服务器以检查 JWS 状态; JWS 将状态 POST 到服务器。

我们没有使用任何第三方组件;这是与 URL.

的简单连接