首页 文章

在另一个groovy中包含一个groovy脚本

提问于
浏览
76

我看过how to simply import a groovy file in another groovy script

我想在一个groovy文件中定义常用函数,并从其他groovy文件中调用这些函数 .

我知道这将使用像脚本语言一样的Groovy,即我不需要类/对象 . 我正在尝试像dsl这样可以在groovy中完成的事情 . 所有变量都将从Java声明,我想在shell中执行groovy脚本 .

这有可能吗?有人可以提供一些例子 .

11 回答

  • 5
    evaluate(new File("../tools/Tools.groovy"))
    

    把它放在脚本的顶部 . 这将引入一个groovy文件的内容(只需用你的groovy脚本替换双引号之间的文件名) .

    我这是一个令人惊讶的名为“Tools.groovy”的课程 .

  • 3

    从Groovy 2.2开始,可以使用新的 @BaseScript AST变换注释声明基本脚本类 .

    例:

    file MainScript.groovy

    abstract class MainScript extends Script {
        def meaningOfLife = 42
    }
    

    file test.groovy

    import groovy.transform.BaseScript
    @BaseScript MainScript mainScript
    
    println "$meaningOfLife" //works as expected
    
  • 28

    我认为最好的选择是以groovy类的形式组织实用程序,将它们添加到类路径中,让主脚本通过import关键字引用它们 .

    例:

    脚本/ DbUtils.groovy

    class DbUtils{
        def save(something){...}
    }
    

    脚本/ script1.groovy:

    import DbUtils
    def dbUtils = new DbUtils()
    def something = 'foobar'
    dbUtils.save(something)
    

    运行脚本:

    cd scripts
    groovy -cp . script1.groovy
    
  • 2

    另一种方法是在groovy类中定义函数,并在运行时解析并将文件添加到类路径中:

    File sourceFile = new File("path_to_file.groovy");
    Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile);
    GroovyObject myObject = (GroovyObject) groovyClass.newInstance();
    
  • 6

    Groovy没有't have an import keyword like typical scripting languages that will do a literal include of another file'的内容(这里提到:Does groovy provide an include mechanism?) .
    由于它的面向对象/类的性质,你必须"play games"来做这样的工作 . 一种可能性是将所有实用程序函数设置为静态(因为您说它们不使用对象),然后在执行shell的上下文中执行静态导入 . 然后你可以调用这些方法,如"global functions" .
    另一种可能性是在创建Shell时使用Binding对象(http://groovy.codehaus.org/api/groovy/lang/Binding.html)并将所需的所有函数绑定到方法(此处的缺点是必须枚举绑定中的所有方法,但您可以使用反射) . 另一种解决方案是覆盖分配给shell的委托对象中的 methodMissing(...) ,这允许您基本上使用 Map 或您想要的任何方法进行动态分派 .

    这里演示了几种这样的方法:http://www.nextinstruction.com/blog/2012/01/08/creating-dsls-with-groovy/ . 如果您想查看特定技术的示例,请与我们联系 .

  • 0

    我这样做的方式是 GroovyShell .

    GroovyShell shell = new GroovyShell()
    def Util = shell.parse(new File('Util.groovy'))
    def data = Util.fetchData()
    
  • -1

    这是一个将一个脚本包含在另一个脚本中的完整示例 .
    只需运行Testmain.groovy文件即可
    包括解释性意见,因为我很喜欢;]

    Testutils.groovy

    // This is the 'include file'
    // Testmain.groovy will load it as an implicit class
    // Each method in here will become a method on the implicit class
    
    def myUtilityMethod(String msg) {
        println "myUtilityMethod running with: ${msg}"
    }
    

    Testmain.groovy

    // Run this file
    
    // evaluate implicitly creates a class based on the filename specified
    evaluate(new File("./Testutils.groovy"))
    // Safer to use 'def' here as Groovy seems fussy about whether the filename (and therefore implicit class name) has a capital first letter
    def tu = new Testutils()
    tu.myUtilityMethod("hello world")
    
  • 94

    如何将外部脚本视为Java类?基于这篇文章:https://www.jmdawson.net/blog/2014/08/18/using-functions-from-one-groovy-script-in-another/

    getThing.groovy 外部脚本

    def getThingList() {
        return ["thing","thin2","thing3"]
    }
    

    printThing.groovy 主要脚本

    thing = new getThing()  // new the class which represents the external script
    println thing.getThingList()
    

    Result

    $ groovy printThing.groovy
    [thing, thin2, thing3]
    
  • 0

    对于后来者来说,似乎groovy现在支持 :load file-path 命令,该命令只是重定向来自给定文件的输入,因此现在包含库脚本是微不足道的 .

    它作为groovysh的输入和加载文件中的一行:
    groovy:000> :load file1.groovy

    file1.groovy可以包含:
    :load path/to/another/file invoke_fn_from_file();

  • 42

    @grahamparks和@snowindy的组合以及几个修改的组合对我在Tomcat上运行的Groovy脚本起了作用:

    Utils.groovy

    class Utils {
        def doSth() {...}
    }
    

    MyScript.groovy:

    /* import Utils --> This import does not work. The class is not even defined at this time */
    Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(new File("full_path_to/Utils.groovy")); // Otherwise it assumes current dir is $CATALINA_HOME
    def foo = groovyClass.newInstance(); // 'def' solves compile time errors!!
    foo.doSth(); // Actually works!
    
  • 29

    经过一番调查后,我得出的结论是,以下方法似乎是最好的 .

    some/subpackage/Util.groovy

    @GrabResolver(name = 'nexus', root = 'https://local-nexus-server:8443/repository/maven-public', m2Compatible = true)
    @Grab('com.google.errorprone:error_prone_annotations:2.1.3')
    @Grab('com.google.guava:guava:23.0')
    @GrabExclude('com.google.errorprone:error_prone_annotations')
    
    import com.google.common.base.Strings
    
    class Util {
        void msg(int a, String b, Map c) {
            println 'Message printed by msg method inside Util.groovy'
            println "Print 5 asterisks using the Guava dependency ${Strings.repeat("*", 5)}"
            println "Arguments are a=$a, b=$b, c=$c"
        }
    }
    

    example.groovy

    #!/usr/bin/env groovy
    Class clazz = new GroovyClassLoader().parseClass("${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy" as File)
    GroovyObject u = clazz.newInstance()
    u.msg(1, 'b', [a: 'b', c: 'd'])
    

    要运行 example.groovy 脚本,请将其添加到系统路径并从任何目录中键入:

    example.groovy
    

    脚本打印:

    Message printed by msg method inside Util.groovy
    Print 5 asterisks using the Guava dependency *****
    Arguments are a=1, b=b, c=[a:b, c:d]
    

    以上示例在以下环境中进行了测试: Groovy Version: 2.4.13 JVM: 1.8.0_151 Vendor: Oracle Corporation OS: Linux

    该示例演示了以下内容:

    • 如何在groovy脚本中使用 Util 类 .

    • Util 类通过将其作为 Grape 依赖项( @Grab('com.google.guava:guava:23.0') )包含来调用 Guava 第三方库 .

    • Util 类可以驻留在子目录中 .

    • 将参数传递给 Util 类中的方法 .

    补充意见/建议:

    • 始终在groovy脚本中使用groovy类而不是groovy脚本来实现可重用的功能 . 上面的示例使用Util.groovy文件中定义的Util类 . 使用groovy脚本实现可重用功能是有问题的 . 例如,如果使用groovy脚本,那么必须使用 new Util() 在脚本底部实例化Util类,但最重要的是,它必须放在名为Util.groovy的文件中 . 有关groovy脚本和groovy类之间差异的更多详细信息,请参阅Scripts versus classes .

    • 在上面的例子中,我使用路径 "${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy" 而不是 "some/subpackage/Util.groovy" . 这将保证始终找到与groovy脚本的位置( example.groovy )相关的 Util.groovy 文件,而不是当前工作目录 . 例如,使用 "some/subpackage/Util.groovy" 将导致在 WORK_DIR/some/subpackage/Util.groovy 处搜索 .

    • 遵循Java类命名约定来命名时髦的脚本 . 我个人更喜欢一个小偏差,其中脚本以较低的字母而不是大写字母开头 . 例如, myScript.groovy 是脚本名称, MyClass.groovy 是类名 . 在某些情况下命名 my-script.groovy 将导致运行时错误,因为生成的类将没有有效的Java类名 .

    • 在JVM世界中,相关功能通常命名为JSR 223: Scripting for the Java . 特别是在groovy中,该功能名为Groovy integration mechanisms . 实际上,可以使用相同的方法从Groovy或Java中调用任何JVM language . 这种JVM语言的一些值得注意的例子是Groovy,Java,Scala,JRuby和JavaScript(Rhino) .

相关问题