Graaljs脚本引擎评估Java脚本字符串条件

问题描述

我正在使用graal.js脚本引擎jdk11。

我们收到两条json字符串消息,一条包含规则/条件(jsRules),另一条包含消息。如果message中的值满足jsRules中的条件,则其值应为1,否则为0。

例如,在下面的代码中,字符串“ message”具有code: CU_USER,因此具有jsRules条件

header.code == 'CU_USER'

应该已经满足,因此下面的eval应该打印为1,但是却给出0。请解释是什么导致了此行为,以及如何获得所需的行为?

public static void process()
{
    int eval =-2 ;
    String jsRules = "{(header.code == 'CU_USER' || header.subcode == 'SD_CODE')?1:0}";
    String message = "{code:'CU_USER'}";
    
    ScriptEngine graalEngine = new ScriptEngineManager().getEngineByName("Graal.js");
    //graalEngine.put("header",message);
    try {
        graalEngine.eval("var header = unescape(" + message + ")");
        eval = (int)graalEngine.eval(jsRules);
        System.out.println("Eval value::  "+eval);
    } catch (ScriptException e) {
        e.printstacktrace();
    }
}

解决方法

您调用unescape({code:'CU_USER'}),而unescape需要一个字符串。因此,您提供的作为参数的对象将转换为字符串(实际上是[object Object]),因此JavaScript端的header变量将保留字符串,而不是您期望的对象。

解决方案是简单地删除unescape,即改为使用graalEngine.eval("var header = " + message);


另一种解决方案是传递Java对象。您似乎已经在注释过的graalEngine.put("header",message);行中进行了尝试。请注意,我想不想传入Java字符串。您通常希望传递的是一个具有code字段的Java对象。请注意,要执行此操作,您需要为引擎启用hostAccess权限(有关更多详细信息,请检查https://github.com/graalvm/graaljs/blob/master/docs/user/ScriptEngine.md)。

解决方案草案:

public static class MyMessageObj {
  public String code = "CU_USER";
}

ScriptEngine graalEngine = new ScriptEngineManager().getEngineByName("graal.js");
Bindings bindings = graalEngine.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("polyglot.js.allowHostAccess",true);
graalEngine.put("header",new MyMessageObj());
eval = (int) graalEngine.eval(jsRules);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...