代码之家  ›  专栏  ›  技术社区  ›  Mehdi Bouzidi

追加CompiledScript或添加两个CompiledScript

  •  3
  • Mehdi Bouzidi  · 技术社区  · 7 年前

    你好,我在用 Groovy 引擎来评估特定脚本。问题是执行时间有点大,所以我想将脚本分为两个脚本。第一个是静态的,可以在内部编译 @PostConstruct 方法,第二个是变量,它取决于用户选择的一些参数。这就是我想做的:

    Bindings bindings;
    CompiledScript scriptC;
    String script1="Static Script";
    String script2="Variable Script";
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("groovy");
    scriptC = ((Compilable) engine).compile(script1); 
    //Execute some instruction to generate 'script2'
    scriptC += ((Compilable) engine).compile(script2);//Please note the += operator
    

    Bindings bindings;
    CompiledScript scriptC;
    String script1="Static Script";
    String script2="Variable Script";
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("groovy");
    scriptC = ((Compilable) engine).compile(script1); 
    //Execute some instruction to generate 'script2'
    scriptC.append(((Compilable) engine).compile(script2));//Please note the append function
    

    这两个代码不能肯定地工作,我使用它们只是为了说明我正在尝试做什么。是否可以将两个脚本合并为一个脚本?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Szymon Stepniak    7 年前

    你不能像那两个一样结合 CompiledScript 物体。对于Groovy,当Groovy脚本被编译时,它会创建一个扩展 groovy.lang.Script 里面有一些方法。在这种情况下,相互添加两个脚本意味着合并两个Java类。

    考虑将两个脚本分开进行评估,作为备选方案。请看以下示例:

    import javax.script.Bindings;
    import javax.script.Compilable;
    import javax.script.CompiledScript;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import javax.script.SimpleBindings;
    
    public class ScriptTest {
    
        public static void main(String[] args) throws ScriptException {
            final ScriptEngineManager manager = new ScriptEngineManager();
            final ScriptEngine engine = manager.getEngineByName("Groovy");
    
            final Bindings bindings = new SimpleBindings();
            bindings.put("a", 3);
    
            final String script1 = "println 'Running first script...'; def c = 2; def d = c + a; return d";
            final CompiledScript compiledScript1 = ((Compilable) engine).compile(script1);
    
            //Execute some instruction to generate 'script2'
            final String script2 = "println 'Running second script...';";
            final CompiledScript compiledScript2 = ((Compilable) engine).compile(script2);
    
            Integer returnedValue = (Integer) compiledScript1.eval(bindings);
            System.out.println("Returned value from the first script: " + returnedValue);
    
            if (returnedValue > 1) {
                compiledScript2.eval(bindings);
            }
        }
    }
    

    创建 已编译脚本 对象是一回事。第二件事是评估这些脚本。如果你总是评估 script1 script2 马上,你只需要:

    compiledScript1.eval(bindings);
    compiledScript2.eval(bindings);
    

    然而 脚本1 可能会返回一些值,根据该值,您可以决定 脚本2 应进行评估。比如说 脚本1 返回 Integer 我会评估 脚本2 仅当返回值大于1时:

    Integer returnedValue = (Integer) compiledScript1.eval(bindings);
    if (returnedValue > 1) {
        compiledScript2.eval(bindings);
    }
    

    或者,您可以在运行后基于绑定值 脚本1 . 比如说 脚本1 修改绑定 a b 并将两者都设置为 true (假设他们持有 boolean 类型):

    compiledScript1.eval(bindings);
    if (bindings.get("a") && bindings.get("b")) {
        compiledScript2.eval(bindings);
    }
    

    调用中定义的函数 脚本1 从…起 脚本2

    比如说 脚本1 定义如下:

    import groovy.json.JsonOutput
    
    def json(Map map) {
        return new JsonOutput().toJson(map)
    }
    
    println json([test: 1])
    

    万一你要打电话 json(map) 内部功能 脚本2 -你可以做到的。看看这个例子:

    import javax.script.Bindings;
    import javax.script.Compilable;
    import javax.script.CompiledScript;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import javax.script.SimpleBindings;
    
    public class ScriptTest {
    
        public static void main(String[] args) throws ScriptException {
            final ScriptEngineManager manager = new ScriptEngineManager();
            final ScriptEngine engine = manager.getEngineByName("Groovy");
    
            final Bindings bindings = new SimpleBindings();
            bindings.put("a", 3);
    
            final String script1 = "import groovy.json.JsonOutput\n" +
                    "\n" +
                    "def json(Map map) {\n" +
                    "    return new JsonOutput().toJson(map)\n" +
                    "}\n" +
                    "\n" +
                    "println json([test: 1])";
    
            final CompiledScript compiledScript1 = ((Compilable) engine).compile(script1);
    
            //Execute some instruction to generate 'script2'
            final String script2 = "println 'Running second script...'; println json([test: 2]);";
            final CompiledScript compiledScript2 = ((Compilable) engine).compile(script2);
    
            compiledScript1.eval(bindings);
            compiledScript2.eval(bindings);
        }
    }
    

    脚本2 定义为:

    println 'Running second script...';
    println json([test: 2]);
    

    运行时,您将在控制台中看到:

    {"test":1}
    Running second script...
    {"test":2}
    

    前两行来自 脚本1 而最后一行是由 脚本2 . 请记住 已编译脚本 保留对同一引擎的引用,以便您可以引用先前评估的脚本中定义的函数。