【问题标题】:Java Web Start doesn't pass arguments to application when running in browserJava Web Start 在浏览器中运行时不会将参数传递给应用程序
【发布时间】:2012-10-18 13:18:27
【问题描述】:

我在将参数传递给使用 Java Web Start 启动的 Java 应用程序时遇到问题。我的系统是 Ubuntu Linux 12.04.1 Precise,但同样的情况也发生在 Windows 7 中。两者都使用 Oracle Java 版本 1.7.0_09。

编辑:我正在研究 Web Start 应用程序是否比普通的小程序更适合我们的需求。小程序的问题在于,如果用户导航离开我们不想要的页面,它就会关闭。 (我们也有兴趣看看是否可以通过使用 Web Start 而不是小程序来解决某个安全问题。)我们想从浏览器启动应用程序,以便我们可以将有关经过身份验证的用户的信息传递给Java 应用程序。要求用户登录应用程序似乎是一个糟糕的解决方案(我们可能必须支持 OAuth 之类的东西)。

我有一个示例程序 CommandLineArgs.java:

public class CommandLineArgs {
    public static void main(String[] args)  {
        System.out.println(String.format("Got %d command line args:", args.length));
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

我把这个打包成罐子了:

javac CommandLineArgs.java
zip cmd.jar CommandLineArgs.class

然后我有一个名为 cmd.jnlp 的 JNLP 文件:

<?xml version="1.0" encoding="utf-8"?>

<!-- Empty codebase means use same directory. -->
<jnlp spec="1.0+" codebase="https://localhost:9876/">
    <information>
        <title>Command Line Args Printer</title>
        <vendor>No one</vendor>
        <homepage href="https://localhost:9876/"/>
        <description>Application that prints the command line arguments that it gets.</description>
    </information>
    <resources>
        <j2se version="1.6+" initial-heap-size="32m" max-heap-size="128m" />
        <property name="jnlp.versionEnabled" value="true"/>

        <jar href="cmd.jar" main="true"/>

    </resources>
    <application-desc main-class="CommandLineArgs">
        <!-- Here are sample arguments I'd like to pass to the program. -->
        <argument>arg1</argument>
        <argument>arg2</argument>
        <argument>arg3</argument>
    </application-desc>
</jnlp>

这是我用于测试的 HTML 页面 cmd.html。 div 元素最初是使用 deployjava.js 创建的:deployJava.launchWebStartApplication('https://localhost:9876/cmd.jnlp')

<!DOCTYPE html>

<html>
<head>
    <title>Java web start command line arguments test</title>

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>

<div id="div1" style="position: relative; left: -10000px; margin: 0px auto; " class="dynamicDiv">
    <embed type="application/x-java-applet;jpi-version=1.7.0_09" width="0" height="0" launchjnlp="https://localhost:9876/cmd.jnlp" docbase="https://localhost:9876/">
</div>

</body>
</html>

让 https 服务器运行的最快方法是使用 Linux 中常见的 openssl 工具。像这样运行服务器时,当前目录应该包含 cmd.html、cmd.jar 和 cmd.jnlp。

sudo cp /etc/ssl/private/ssl-cert-snakeoil.key .
sudo chmod 666 ssl-cert-snakeoil.key
openssl req -batch -new -x509 -key ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key.crt
openssl s_server -cert ssl-cert-snakeoil.key.crt -key ssl-cert-snakeoil.key -accept 9876 -WWW

现在,如果我浏览https://localhost:9876/cmd.html,我可以运行该应用程序。 Java 控制台打开并打印出来。请注意,有 0 个命令行参数。

   JNLP Ref (absolute): https://localhost:9876/cmd.jnlp
    Match: beginTraversal
Match: digest selected JREDesc: JREDesc[version 1.6+, heap=33554432-134217728, args=null, href=null, sel=false, null, null], JREInfo: JREInfo for index 0:
    platform is: 1.7
    product is: 1.7.0_09
    location is: http://java.sun.com/products/autodl/j2se
    path is: /opt/jre1.7.0_09/bin/java
    args is: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001
    native platform is: Linux, amd64 [ x86_64, 64bit ]
    JavaFX runtime is: JavaFX 2.2.3 found at /opt/jre1.7.0_09/
    enabled is: true
    registered is: true
    system is: true

    Match: ignoring maxHeap: 134217728
    Match: selecting InitHeap: 33554432
    Match: digesting vmargs: null
    Match: digested vmargs: [JVMParameters: isSecure: true, args: ]
    Match: JVM args after accumulation: [JVMParameters: isSecure: true, args: ]
    Match: digest LaunchDesc: null
    Match: digest properties: []
    Match: JVM args: [JVMParameters: isSecure: true, args: ]
    Match: endTraversal ..
    Match: JVM args final: -Xms32m
    Match: Running JREInfo Version    match: 1.7.0.09 == 1.7.0.09
     Match: Running JVM args match: have:<-Xms32m     satisfy want:<-Xms32m>
Got 0 command line args:

另一方面,如果我从命令行 (javaws cmd.jnlp) 运行 javaws,我会在 java 控制台中得到它。现在有 3 个命令行参数。

    Match: beginTraversal
Match: digest selected JREDesc: JREDesc[version 1.6+, heap=33554432-134217728, args=null, href=null, sel=false, null, null], JREInfo: JREInfo for index 0:
    platform is: 1.7
    product is: 1.7.0_09
    location is: http://java.sun.com/products/autodl/j2se
    path is: /opt/jre1.7.0_09/bin/java
    args is: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001
    native platform is: Linux, amd64 [ x86_64, 64bit ]
    JavaFX runtime is: JavaFX 2.2.3 found at /opt/jre1.7.0_09/
    enabled is: true
    registered is: true
    system is: true

    Match: ignoring maxHeap: 134217728
    Match: selecting InitHeap: 33554432
    Match: digesting vmargs: null
    Match: digested vmargs: [JVMParameters: isSecure: true, args: ]
    Match: JVM args after accumulation: [JVMParameters: isSecure: true, args: ]
    Match: digest LaunchDesc: null
    Match: digest properties: []
    Match: JVM args: [JVMParameters: isSecure: true, args: ]
    Match: endTraversal ..
    Match: JVM args final: -Xms32m
    Match: Running JREInfo Version    match: 1.7.0.09 == 1.7.0.09
     Match: Running JVM args match: have:<-Djnlp.versionEnabled=true -Xms32m     satisfy want:<-Xms32m>
Got 3 command line args:
arg1
arg2
arg3

我做错了吗?为什么在浏览器中运行时参数不传递给我的程序?

我发现帖子Java WS application ignoring arguments sporadically 似乎描述了同样的问题。 posdef 的解决方案是从 jnlp 文件中的 jnlp 元素中删除 href 属性,但我没有该属性。

【问题讨论】:

  • 如果不是applet,这段代码如何在浏览器中运行?如果它是一个小程序,它通常会期望接收参数而不是命令行参数。
  • 感谢您的回复。我更新了问题并解释了我们想要实现的目标。我们已经有了一个小程序,但我相信我们想把它变成一个独立于浏览器窗口/选项卡运行的应用程序。
  • 实际上我设法重新创建了一个非常相似的问题,如此处所述。使用非常小的 test.jnlp + deployJava.launchWebStartApplication('test.jnlp') 参数不会传递给 main。如果我从本地磁盘启动相同的下载 java 文件,它会完美运行。您是否碰巧找到了解决此问题的方法?
  • 没找到解决办法,只好放弃了,继续做其他事情。

标签: java java-web-start java-ws


【解决方案1】:

application-desc 用于 WebStart 应用程序,applet-desc 用于小程序。

【讨论】:

  • 感谢您的回复。我更新了问题并解释了我们想要实现的目标。我们已经有了一个成熟的小程序,但它实际上并没有在页面上运行,而是在一个单独的窗口中运行。我们希望 Java 应用程序在用户离开页面时保持打开状态,我的印象是您无法使用 applet 做到这一点。当然,如果我的假设有误,我会很感激您的意见。
  • 是的,听起来您想要一个 WebStart 应用程序而不是一个小程序(在极少数情况下您实际上想要使用一个小程序)。
【解决方案2】:

我们还想看看是否可以通过使用 Web Start 而不是小程序来解决某个安全问题。

应用于基于 JWS 的应用程序的安全环境。总是与应用于小程序的非常相似。一些小的区别是System.exit(n) 在小程序(甚至是受信任的小程序)中始终受到限制,并且 JWS 提供了介于沙盒和受信任之间的中间级别的安全性。

在 Oracle 收购这两种形式的插件之前,Sun 努力整合它们。

所以这个问题的简短回答是“不”。如果您可以在 JWS 应用程序中执行此操作,那么您应该可以在小程序中执行此操作。

【讨论】:

  • 实际上,我们遇到的问题值得提出自己的问题。简而言之,有人在代理后面运行我们的小程序。我们的小程序经历了一些短暂的冻结,当我们将调试器附加到 Java 时,我们发现当创建一个新的匿名类时,类加载器会检查它是否正常,Java 中有人发出网络请求以找出一些东西(不知道什么),当 Java 尝试解析主机名时,一切都冻结了。我最好的猜测是它无法解析主机名,因为它必须使用代理而它没有。我想知道我们是否可以避免这个权限检查。
  • 这是关于安全问题的完整问题:stackoverflow.com/questions/13025957/…
【解决方案3】:

根据 Oracle 文档

“属性元素定义了一个系统属性,可以通过 System.getProperty 和 System.setProperties 方法获得。它有两个必需的属性:名称和值。”

那么给出这个例子:

<property name="key" value="overwritten"/> 

要检索 Java 类中的值:

System.getProperty("key");

【讨论】:

  • 我意识到这与将“String[] args”传递给 main 不同,但是使用 javaws 你的选择有限。如果您需要它成为常规的“String [] args”,您总是可以制作一个引导程序。即创建另一个主类来处理拉取系统属性,然后启动“真实”应用程序,将值作为数组传递。
猜你喜欢
  • 2011-01-16
  • 2012-06-15
  • 2017-08-12
  • 2011-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-26
相关资源
最近更新 更多