使用 Rhino 代替 ScriptEngine 在 Java 中运行 Javascript 代码

Posted

技术标签:

【中文标题】使用 Rhino 代替 ScriptEngine 在 Java 中运行 Javascript 代码【英文标题】:Using Rhino instead of ScriptEngine to run Javascript code in Java 【发布时间】:2016-01-16 12:08:01 【问题描述】:

基于converting string representation of unknown date-format to Date in java 的讨论,我想在我的 App-Engine 项目中使用 javascript Date 函数。但是,ScriptEngine 不适用于 App-Engine。所以我需要一些帮助来转换为 Rhino。这是我需要转换的 ScriptEngine 代码:

ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine engine = scriptEngineManager.getEngineByName("JavaScript");
String script = "var date = new Date('" + dateInUnknownFormat + "'); var timestamp = date.getTime();";
engine.eval(script);
long timestamp = ((Double) engine.get("timestamp")).longValue();

以下操作无效

private static long parseDateUsingRhino(String dateInUnknownFormat)
    Context mozillaJsContext = Context.enter();
    Scriptable scope = mozillaJsContext.initStandardObjects();
    String script = "var date = new Date('" + dateInUnknownFormat + "'); var timestamp = date.getTime();";
    Object obj = mozillaJsContext.evaluateString( scope, script, "TestScript", 1, null );
    Double timeDouble = Double.parseDouble((String) obj);
    long timestamp = timeDouble.longValue();
    return  timestamp;

我已经用null""替换了"TestScript"

【问题讨论】:

您是否忘记添加错误跟踪? 没有。我把它拿出来,因为它无关紧要。我只是不知道如何正确编写代码。无关紧要是因为我得到不同的错误或没有错误取决于我的尝试。但最终,我永远无法让 Rhino 产生结果。显然,知道 Rhino 是如何工作的人,将 ScriptEngine 版本翻译成 Rhino 是没有问题的。 【参考方案1】:

你应该先这样尝试,看看它是否有效:

private static long parseDateUsingRhino(String dateInUnknownFormat)
        Context mozillaJsContext = Context.enter();
        Scriptable scope = mozillaJsContext.initStandardObjects();
        String script = "var date = new Date().getTime();";
        Object result = mozillaJsContext.evaluateString( scope, script, "", 1, null );
        return Long.valueOf(Context.toString(result));
    

根据this,您接下来需要做的就是像这样传递dateInUnknownFormat 变量,不需要java 字符串连接(上下文足够聪明,可能会将java 方法的可访问变量视为javascript 中的全局变量范围):

String script = "var date = new Date(dateInUnknownFormat).getTime();";

【讨论】:

我遇到了类似的问题,所以我尝试应用您的解决方案并得到java.lang.NumberFormatException: For input string: "undefined"。这就是您具有"var date = new Date().getTime();"的确切代码块 你在发布之前测试过这段代码吗?它不起作用。【参考方案2】:

在 JavaScript 引擎执行的脚本中,你只需要使用new Date(dateString).getTime() 计算你想要的值(你也可以使用"var date = new Date(dateString); date.getTime()";)。您不应该将结果存储在变量中。

我还对你的方法做了两个补充:

要将评估结果转换为字符串,应使用Context.toString(obj)。由于这里的结果实际上是一个数字,我们可以直接使用Context.toNumber(obj),它返回一个double,并将其转换为long。 我添加了一个从Context 退出的finally 块。

工作代码:

private static long parseDateUsingRhino(String dateInUnknownFormat) 
    Context mozillaJsContext = Context.enter();
    try 
        Scriptable scope = mozillaJsContext.initStandardObjects();
        String script = "new Date('" + dateInUnknownFormat + "').getTime()";
        Object obj = mozillaJsContext.evaluateString(scope, script, "TestScript", 1, null);
        return (long) Context.toNumber(obj);
     finally 
        Context.exit();
    

示例:

System.out.println(parseDateUsingRhino("2015-10-25T15:06:42.000Z")); // prints 1445785602000

附注:这是用 Rhino 1.7.7 测试的。

【讨论】:

以上是关于使用 Rhino 代替 ScriptEngine 在 Java 中运行 Javascript 代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 ScriptManager (Rhino) 从 Java 中使用 Javascript HTML5 类型数组,如何?

如何销毁 Java ScriptEngine 实例?

java如何执行javascript操作html

Java:在应用程序中嵌入脚本引擎:JSR 223 (ScriptEngine) 仍然是一个好的解决方案吗?

使用 Rhino(Mozilla 的 rhino)的优点

ScriptEngine执行复杂js报数组越界