【问题标题】:Load script from groovy script从 groovy 脚本加载脚本
【发布时间】:2012-02-18 17:32:33
【问题描述】:

文件1.groovy

def method() {
   println "test"
}

文件2.groovy

method()

我想在运行时从 File1.groovy 加载/包含函数/方法,相当于 ruby​​s/rake 的加载。它们位于两个不同的目录中。

【问题讨论】:

    标签: groovy load


    【解决方案1】:

    如果您不介意 file2 中的代码位于 with 块中,您可以这样做:

    new GroovyShell().parse( new File( 'file1.groovy' ) ).with {
      method()
    }
    

    另一种可能的方法是将file1.groovy 更改为:

    class File1 {
      def method() {
        println "test"
      }
    }
    

    然后在file2.groovy 中,您可以使用mixin 添加来自file1 的方法

    def script = new GroovyScriptEngine( '.' ).with {
      loadScriptByName( 'file1.groovy' )
    } 
    this.metaClass.mixin script
    
    method()
    

    【讨论】:

    • 另一个问题,简短的相关。如果我想按预期运行脚本,则脚本不是类。不调用方法。 Lika 运行或执行方法。
    • 你可能想要GroovyShell.evaluate
    • @tim_yates 我认为您应该将 loadScriptByName( 'file1.groovy' ) 更改为 loadScriptByName( 'file1' )
    • @despot 真的吗?我觉得不应该
    • 您的解决方案让我走上了正确的道路,但它并不完全正确。你不需要在你的加载脚本中添加一个类。我会给出我的答案。
    【解决方案2】:

    您可以使用 GroovyShell 在 Groovy 中评估任何表达式或脚本。

    文件2.groovy

    GroovyShell shell = new GroovyShell()
    def script = shell.parse(new File('/path/file1.groovy'))
    script.method()
    

    【讨论】:

    • 你知道是否有可能获得当前脚本中的方法。这个 += 脚本。如果你能理解。这就是我所追求的。
    • 调用方式错误。它应该是 script.invokeMethod("method", args) 假设 'method' 是静态的。
    • 这对我来说效果很好。 file1.groovy 既不需要是一个实际的类,也不需要它的方法是静态的。
    【解决方案3】:

    如果file1.groovy 是一个实际的类class File1 {...},那将是最简单的。

    鉴于此,另一种方法是将文件加载到GroovyClassLoader

    this.class.classLoader.parseClass("src/File1.groovy")
    
    File1.method() 
    
    File1.newInstance().anotherMethod()
    

    【讨论】:

    【解决方案4】:

    我迟到了,但是。这就是我们一直在实现您的要求的方式。所以,我有一个像这样的 file1.gsh:

    文件 1:

    println("this is a test script")
    
    def Sometask(param1, param2, param3)
    {
        retry(3){
            try{
                ///some code that uses the param
            }
            catch (error){
                println("Exception throw, will retry...")
                sleep 30
                errorHandler.call(error)
            }
        }
    }
    
    return this;
    

    而在另一个文件中,这些函数可以通过先实例化来访问。所以在文件 2 中。

    文件2:

    def somename
    somename = load 'path/to/file1.groovy'
     //the you can call the function in file1 as
    
    somename.Sometask(param1, param2, param3)
    

    【讨论】:

    • 在 Jenkins 管道上完美运行! (注意:起初,我忘记了脚本末尾的return this,所以load 正在返回null
    • load 'path/to/file' 工作完美,不知道为什么这么难找到,虽然如果我没记错的话,当前缀为 ./ 时它不起作用
    • “this”返回什么?它应该像 groovy SDK 中的 Script 对象或某物。 (我已经检查了“脚本”对象,但其中没有“加载”方法。)
    • 'load' 只有在 jenkins 上下文中运行时才有意义。它不是 groovy 语言的一部分。
    • 正如上面提到的@Hoobajoob,这是一个 Jenkins 管道 DSL,而不是 Groovy 语言功能。
    【解决方案5】:

    这是我正在使用的。

    1:将any_path_to_the_script.groovy写成一个类

    2:在调用脚本中,使用:

    def myClass = this.class.classLoader.parseClass(new File("any_path_to_the_script.groovy"))
    myClass.staticMethod()
    

    它在 Jenkins Groovy 脚本控制台中运行。我没有尝试过非静态方法。

    【讨论】:

    【解决方案6】:

    @tim_yates 使用metaClass.mixin 的答案应该可以在不需要对file1.groovy 进行任何更改的情况下工作(即mixin 与脚本对象),但不幸的是metaClass.mixin 中有一个错误导致SO这种情况下的错误(请参阅GROOVY-4214 关于此特定问题)。但是,我使用以下 selective mixin:

    解决了这个错误
    def loadScript(def scriptFile) {
       def script = new GroovyShell().parse(new File(scriptFile))
       script.metaClass.methods.each {
           if (it.declaringClass.getTheClass() == script.class && ! it.name.contains('$') && it.name != 'main' && it.name != 'run') {
               this.metaClass."$it.name" = script.&"$it.name"
           }
       }
    }
    
    loadScript('File1.groovy')
    method()
    

    上述解决方案无需更改File1.groovyFile2.groovy 中的调用者(除了需要引入对loadScript 函数的调用)。

    【讨论】:

    • 这很棒。将loadScript重命名为importScript可能更准确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 2012-07-10
    相关资源
    最近更新 更多