当前位置: 首页 > 知识库问答 >
问题:

将Java实现的函数添加到Nashorn的全局范围中

公羊光明
2023-03-14

我正在尝试迁移/更新我的项目,以使用Rhino的Nashorn。我用Java实现了一些全局实用程序函数,并将其添加到目标脚本引擎的全局范围中,典型的例子是log(message)

在Rhino中,它是通过

public static class LogFunction extends org.mozilla.javascript.BaseFunction {
    @Override
    public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
        ...
    }
}

其实例已添加到目标范围。如果是纳肖恩,该怎么办?我找不到如何为Nashorn实现独立函数。

共有2个答案

任长卿
2023-03-14

问了这个问题一段时间后,我又谷歌了一下,发现了这篇文章:http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-December/002520.html

*)在JDK(或您自己的@FunctionInterface)中实现任何@FunctionInterface接口,并在javax中传递/放置相同的对象。剧本绑定,甚至全局范围。脚本可以像访问函数一样访问这些函数。

*)实现jdk。纳肖恩。应用程序编程接口。脚本编写。并在类中实现“call”方法。同样,nashorn灵活的基于dynalink的链接器将以简单的方式处理JSObject。好像这是一个函数。这也可以用于在Java代码中实现“构造函数”(newObject方法),等等。

我决定使用JSObject实现,我的代码看起来更像Rhino,比Sundararajan的答案中推荐的方法更接近我的原始代码。不确定它们之间是否存在性能差异。

import jdk.nashorn.api.scripting.AbstractJSObject;

public static class PrintFunction extends AbstractJSObject {

    public PrintFunction() {
    }

    @Override
    public boolean isFunction() {
        return true;
    }

    @Override
    public Object call(Object thiz, Object... args) {
        ... do something ...

        return null;
    }
}

...

void onInitScriptObjects(Bindings scope) {
    scope.put("print", new PrintFunction());
}
秦永望
2023-03-14

您可以轻松地在Java中实现脚本函数。您只需实现任何@FunctionInterface即可(https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html)接口,并通过调用ScriptEngine将其作为全局变量公开。放(https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngine.html#put-爪哇。lang.String-java。lang.Object-)方法。下面的示例实现了两个用Java代码实现的脚本“函数”。

import javax.script.*;
import java.util.function.*;
import java.util.Random;

public class Main {
  public static void main(String[] args) throws Exception {
     ScriptEngineManager m = new ScriptEngineManager();
     ScriptEngine e = m.getEngineByName("nashorn");

     // expose 'log' function - any @FunctionInterface Java
     // object can be exposed as 'function'
     e.put("log", (Consumer<String>)System.out::println);

     Random r = new Random();
     // expose 'next gaussian' as script global function
     e.put("gaussian", (Supplier<Double>)r::nextGaussian);

     // call functions implemented in Java!
     e.eval("log('hello')");
     e.eval("print(gaussian())");
     e.eval("print(gaussian())");
  }
}
 类似资料:
  • 如何用webpack和babel编译我的代码,使导出的函数在全局范围内可用? 比如说: 应该在下可用。 当我刚刚运行时,我得到了我所期望的: 但是webpack的输出如下所示: end<code>测试</code>函数在全局范围内不可用。

  • 本文向大家介绍Yii2中添加全局函数的方法分析,包括了Yii2中添加全局函数的方法分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Yii2中添加全局函数的方法。分享给大家供大家参考,具体如下: 方法一 这种方法就是直接在入口文件web/index.php里面写函数,示例代码如下: 这个方法虽然可以实现,但是本人不推荐,因为改了框架本身的代码,而且如果全局函数多了的话,也不好管理。 方法

  • 参考leetcode的javascript解决方案-添加两个数字https://leetcode.com/problems/add-two-numbers/ 为什么列表范围在头部范围改变时不改变,即头部改变时。next被分配给新节点引用,head被分配回head。接下来,为什么要列出它。next没有改变,与整个链表保持相同 请参考以下解决方案- 我试了下面的东西,但它给出了一些不同的输出,当a.n

  • 问题内容: 我有一个简单的Java类,其中包含一些方法: 我想创建此类的实例,并允许Javascript代码直接调用方法,如下所示: 我目前只能弄清楚的唯一方法是使用 然后在Javascript代码中使用。我还可以使用Javascript为每个方法编写包装器函数,但是应该有一种更简单的方法来自动为类的所有公共方法执行此操作。 问题答案: 我对Rhino并不是很熟悉,但是这样的方法应该可以工作: 只

  • 问题内容: 我遇到下面显示的行未将变量存储到全局范围的问题: 我究竟做错了什么?我需要将其包装到单独的函数中还是什么? 问题答案: 该代码在收到响应之前运行。 这就是为什么。 在这里,您可以看到警报发生故障。默认情况下,AJAX请求不会阻止后续代码运行。 这就是拥有 回调 方法的全部目的。该方法在适当的时间被调用,而不是依赖于同步执行。

  • 问题内容: 我有一个Java 7程序,该程序加载成千上万个对象(组件),每个对象具有许多参数(存储在中),并在这些对象上执行各种Rhino脚本以计算其他派生参数,这些参数又存储回该对象的中。在运行每个脚本之前,将创建一个对象,该对象由该对象的映射支持,该映射在脚本运行期间用作JavaScript的作用域。 作为一个简单的示例,以下代码创建一个a = 10和b = 20的代码,并执行脚本,结果将其存