在嵌入式groovy脚本中确定范围

时间:2010-11-22 12:49:08

标签: scripting groovy scope

在我的应用中,我使用Groovy作为脚本语言。为了让我的客户更容易,我有一个全局范围,我在其中定义了辅助类和常量。

目前,我需要在每次执行用户脚本时运行脚本(构建全局范围):

context = setupGroovy();
runScript( context, "global.groovy" ); // Can I avoid doing this step every time?
runScript( context, "user.groovy" );

有没有办法设置这个全局范围一次,只需告诉嵌入式脚本解释器:“如果你找不到变量,请看这里”?这样,我可以运行一次全局脚本。

注意:此处的安全性不是问题,但如果您知道某种方法可以确保用户无法修改全局范围,那么这是一个额外的优势。

2 个答案:

答案 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();