代码之家  ›  专栏  ›  技术社区  ›  Aaron Digulla

嵌入式groovy脚本中的作用域

  •  2
  • Aaron Digulla  · 技术社区  · 15 年前

    在我的应用程序中,我使用Groovy作为脚本语言。为了方便我的客户,我有一个全局范围,在这里我定义了helper类和常量。

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

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

    有没有一种方法可以设置一次全局作用域,然后告诉嵌入式脚本解释器:“如果找不到变量,请看这里”?这样,我可以运行一次全局脚本。

    注意:这里的安全性不是问题,但是如果您知道一种确保用户不能修改全局范围的方法,那么这是一个额外的优点。

    2 回复  |  直到 15 年前
        1
  •  0
  •   Northover    15 年前

    不知羞耻地从groovy.codehaus偷走:

    最完整的解决方案 希望将groovy脚本嵌入 他们的服务器并重新加载 修改时是 GroovyScript引擎。你初始化 GroovyScriptEngine有一组 类路径的根,可以是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

    你想要那种东西吗?

        2
  •  0
  •   Aaron Digulla    15 年前

    一个简单的解决方案是使用 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();