3

您好我正在使用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

这两个代码肯定不起作用,我用它们只是为了说明我正在尝试做的事情。是否可以将两个脚本合并为一个脚本?

4

1 回答 1

1

你不能像那样组合两个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);
        }
    }
}

创建CompiledScript对象是一回事。第二件事是评估这些脚本。如果您总是立即进行评估script1script2那么您只需要:

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

但是script1可能会返回一些值,并且基于该值您可以决定是否script2应该评估。假设script1返回一个Integer,我将script2仅在返回值大于 1 时进行评估:

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

或者,您可以在运行后基于绑定值script1。假设script1修改绑定a并将b两者都设置为true(假设它们持有boolean类型):

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

调用script1from中定义的函数script2

假设script1定义如下:

import groovy.json.JsonOutput

def json(Map map) {
    return new JsonOutput().toJson(map)
}

println json([test: 1])

如果你必须在里面调用json(map)函数script2- 你可以做到。看看这个例子:

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);
    }
}

script2定义为:

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

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

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

前两行来自,script1而最后一行由 生成script2。请记住,两者都CompiledScript持有对同一引擎的引用,因此您可以引用在先前评估的脚本中定义的函数。

于 2018-02-18T11:05:16.173 回答