在我的应用中,我使用Groovy作为脚本语言。为了让我的客户更容易,我有一个全局范围,我在其中定义了辅助类和常量。
目前,我需要在每次执行用户脚本时运行脚本(构建全局范围):
context = setupGroovy();
runScript( context, "global.groovy" ); // Can I avoid doing this step every time?
runScript( context, "user.groovy" );
有没有办法设置这个全局范围一次,只需告诉嵌入式脚本解释器:“如果你找不到变量,请看这里”?这样,我可以运行一次全局脚本。
注意:此处的安全性不是问题,但如果您知道某种方法可以确保用户无法修改全局范围,那么这是一个额外的优势。
答案 0 :(得分:1)
从groovy.codehaus无耻地偷走了:
最完整的解决方案 谁想要嵌入groovy脚本 他们的服务器并重新加载它们 修改是 的GroovyScriptEngine。你初始化了 GroovyScriptEngine有一套 CLASSPATH就像可以是URL的根 或目录名称。那你可以 在那些内部执行任何Groovy脚本 根。 GSE也将跟踪 脚本之间的依赖关系 如果修改了任何依赖脚本 整棵树将被重新编译 重新加载。
此外,每次运行时 脚本你可以传入一个绑定 包含脚本的属性 可以访问。在中设置的任何属性 脚本也将在那里提供 脚本运行后的绑定。这里 是一个简单的例子:
/my/groovy/script/path/hello.groovy:
output = "Hello, ${input}!"
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
String[] roots = new String[] { "/my/groovy/script/path" };
GroovyScriptEngine gse = new GroovyScriptEngine(roots);
Binding binding = new Binding();
binding.setVariable("input", "world");
gse.run("hello.groovy", binding);
System.out.println(binding.getVariable("output"));
This will print "Hello, world!".
找到:here
这样的事情对你有用吗?
答案 1 :(得分:1)
一个简单的解决方案是使用groovy.lang.GroovyShell
中的代码:您可以像这样预编译脚本:
GroovyCodeSource gcs = AccessController.doPrivileged( new PrivilegedAction<GroovyCodeSource>() {
public GroovyCodeSource run() {
return new GroovyCodeSource( scriptCode, fileName, GroovyShell.DEFAULT_CODE_BASE );
}
} );
GroovyClassLoader loader = AccessController.doPrivileged( new PrivilegedAction<GroovyClassLoader>() {
public GroovyClassLoader run() {
return new GroovyClassLoader( parentLoader, CompilerConfiguration.DEFAULT );
}
} );
Class<?> scriptClass = loader.parseClass( gcs, false );
这是昂贵的部分。现在使用InvokeHelper
将已编译的代码绑定到上下文(使用全局变量)并运行它:
Binding context = new javax.script.Binding();
Script script = InvokerHelper.createScript(scriptClass, context);
script.run();