【问题标题】:Scoping in embedded groovy scripts嵌入式 groovy 脚本中的范围
【发布时间】:2011-05-13 19:57:57
【问题描述】:

在我的应用程序中,我使用 Groovy 作为脚本语言。为了让我的客户更轻松,我有一个全局范围,我可以在其中定义帮助程序类和常量。

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

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

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

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

【问题讨论】:

    标签: scripting groovy scope


    【解决方案1】:

    从 groovy.codehaus 无耻地盗取:

    为人们提供最完整的解决方案 谁想要将 groovy 脚本嵌入 他们的服务器并让他们重新加载 在修改是 Groovy 脚本引擎。你初始化 GroovyScriptEngine 带有一组 CLASSPATH 像可以是 URL 的根 或目录名称。然后你可以 在其中执行任何 Groovy 脚本 根。 GSE 还将跟踪 脚本之间的依赖关系,以便 如果修改了任何依赖脚本 整个树将被重新编译并 重新加载。

    此外,每次运行 您可以传入一个 Binding 的脚本 包含脚本的属性 可以访问。中设置的任何属性 脚本也将在其中可用 脚本运行后绑定。这里 是一个简单的例子:

    /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】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        相关资源
        最近更新 更多