如何存储 ScriptManager 中的函数句柄以备后用?

tl;博士:
我如何/如何在 Java 中存储多个 js 函数的函数句柄以供以后使用?目前我有两个想法:

  1. 创建多个 ScriptEngine 实例,每个实例包含一个加载的函数。将它们按列存储在地图中,列表中每列有多个条目。看起来像是一个很大的开销,这取决于 ScriptEngine 实例的“重”......

  2. 一些将相同目标字段的方法附加到数组的 Javascript 解决方案。还不知道如何从 java 端访问它,但也不喜欢它。想让脚本文件尽可能愚蠢。

     var test1 = test1 || [];
     test1.push(function(input) { return ""; });
    
  3. ???

想法或建议?


告诉我更多:
我有一个项目,其中有一个包含脚本文件的目录(javascript,预计会有一百多个文件,将来会增长)。这些脚本文件的名称如下:test1;toupper.jstest1;trim.jstest2;capitalize.js。分号之前的名称是脚本将要处理的列/字段,分号之后的部分是人类可读的文件功能描述(简化示例)。所以在这个例子中,有两个脚本将分配给“test1”列,一个脚本分配给“test2”列。 js-function 模板基本上是这样的:

    function process(input) { return ""; };

我的想法是,在服务器启动时加载(并评估/编译)所有脚本文件,然后在需要时按列使用加载的函数。到目前为止,一切都很好。

我可以使用以下代码加载/评估单个函数。示例使用 GraalVM,但也应该可以用其他语言重现。

    final ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
    final Invocable invocable = (Invocable) engine;
    
    engine.eval("function process(arg) { return arg.toUpperCase(); };");
    var rr0 = invocable.invokeFunction("process","abc123xyz"); // rr0 = ABC123XYZ

但是当我加载/评估下一个具有相同名称的函数时,前一个函数将被覆盖 - 逻辑上,因为它的函数名称相同。

    engine.eval("function process(arg) { return arg + 'test'; };");
    var rr1 = invocable.invokeFunction("process","abc123xyz"); // rr1 = abc123xyztest
iCMS 回答:如何存储 ScriptManager 中的函数句柄以备后用?

这就是我要做的。

推荐使用 Graal.js 的方法是通过多语言 API:https://www.graalvm.org/reference-manual/embed-languages/

使用 ScriptEngine API 可能不一样,但这里是使用多语言 API 的示例。

  1. 将函数定义包裹在 ()
  2. 将函数返回给 Java
  3. 未图示,但您可能构建了从列名到要调用的函数列表的映射。
  4. 调用数据上的函数。
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.proxy.*;

public class HelloPolyglot {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
        try (Context context = Context.create()) {
            Value toUpperCase = context.eval("js","(function process(arg) { return arg.toUpperCase(); })");
            Value concatTest = context.eval("js","(function process(arg) { return arg + 'test'; })");

            String text = "HelloWorld";
            text = toUpperCase.execute(text).asString();
            text = concatTest.execute(text).asString();

            System.out.println(text);
        }
    }
}

现在,Value.execute() 返回一个 Value,为了简单起见,我将其强制转换为带有 asString() 的 Java 字符串,但您不必这样做,您可以对 {{ 1}}(这是 Value 的 API:https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html)。

本文链接:https://www.f2er.com/441672.html

大家都在问