我已阅读how to simply import a groovy file in another groovy script
我想在一个groovy文件中定义常用函数,并从其他groovy文件中调用这些函数。
我理解这会像脚本语言一样使用Groovy,即我不需要类/对象。我正在尝试像dsl一样可以在groovy中完成。所有变量都将从Java声明,我想在shell中执行groovy脚本。
这有可能吗?有人可以提供一些例子。
答案 0 :(得分:96)
evaluate(new File("../tools/Tools.groovy"))
将它放在脚本的顶部。这将引入一个groovy文件的内容(只需用你的groovy脚本替换双引号之间的文件名)。
我这是一个令人惊讶的名为“Tools.groovy”的课程。
答案 1 :(得分:43)
从Groovy 2.2开始,可以使用新的@BaseScript
AST转换注释声明基本脚本类。
示例:
文件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
答案 2 :(得分:36)
另一种方法是在groovy类中定义函数并解析并在运行时将文件添加到类路径中:
File sourceFile = new File("path_to_file.groovy");
Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile);
GroovyObject myObject = (GroovyObject) groovyClass.newInstance();
答案 3 :(得分:30)
我认为最好的选择是以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
答案 4 :(得分:6)
Groovy没有像典型的脚本语言那样的导入关键字,它会包含另一个文件的内容(这里提到:Does groovy provide an include mechanism?)。
由于它的对象/类导向性质,你必须“玩游戏”来制作像这样的工作。一种可能性是将所有实用程序函数设置为静态(因为您说它们不使用对象),然后在执行shell的上下文中执行静态导入。然后你可以称这些方法为“全局函数”。
另一种可能性是在创建Shell时使用绑定对象(http://groovy.codehaus.org/api/groovy/lang/Binding.html)并将所需的所有函数绑定到方法(这里的缺点是必须枚举绑定中的所有方法,但你可以或许使用反思)。另一种解决方案是覆盖分配给shell的委托对象中的methodMissing(...)
,这允许您基本上使用地图或您想要的任何方法进行动态分派。
这里展示了其中一些方法:http://www.nextinstruction.com/blog/2012/01/08/creating-dsls-with-groovy/。如果您想查看特定技术的示例,请告诉我。
答案 5 :(得分:6)
我这样做的方式是使用GroovyShell
。
GroovyShell shell = new GroovyShell()
def Util = shell.parse(new File('Util.groovy'))
def data = Util.fetchData()
答案 6 :(得分:5)
以下是将一个脚本包含在另一个脚本中的完整示例
只需运行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")
答案 7 :(得分:5)
如何将外部脚本视为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()
<强>结果强>
$ groovy printThing.groovy
[thing, thin2, thing3]
答案 8 :(得分:0)
对于后来者来说,似乎groovy现在支持:load file-path
命令,它只是重定向来自给定文件的输入,因此现在包含库脚本是微不足道的。
它作为groovysh&amp;的输入。作为加载文件中的一行:
groovy:000> :load file1.groovy
file1.groovy可以包含:
:load path/to/another/file
invoke_fn_from_file();
答案 9 :(得分:0)
@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!
答案 10 :(得分:0)
Groovy可以完全像Java一样导入其他groovy类。只要确保库文件的扩展名是.groovy。
$ cat lib/Lib.groovy
package lib
class Lib {
static saySomething() { println 'something' }
def sum(a,b) { a+b }
}
$ cat app.gvy
import lib.Lib
Lib.saySomething();
println new Lib().sum(37,5)
$ groovy app
something
42
答案 11 :(得分:-1)
经过一番调查后,我得出结论,以下方法似乎是最好的。
<强>一些/子包/ Util.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
要运行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
以上示例在以下环境中进行了测试:Util
该示例演示了以下内容:
Util
类。Guava
类调用Grape
第三方库,将其包含为@Grab('com.google.guava:guava:23.0')
依赖项(Util
)。Util
类可以驻留在子目录中。new Util()
类中的方法。其他意见/建议:
"${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy"
在脚本底部实例化Util类,但最重要的是,它必须放在名为Util.groovy的文件中。有关groovy脚本和groovy类之间差异的更多详细信息,请参阅Scripts versus classes。"some/subpackage/Util.groovy"
代替Util.groovy
。这将保证始终可以找到与常规脚本位置(example.groovy
)相关的"some/subpackage/Util.groovy"
文件,而不是当前工作目录。例如,使用WORK_DIR/some/subpackage/Util.groovy
会导致在myScript.groovy
进行搜索。MyClass.groovy
是脚本名称,my-script.groovy
是类名。命名func keyboardWillChangeFrameWithNotification(_ notification: Notification, showsKeyboard: Bool) {
let userInfo = notification.userInfo!
let animationDuration: TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
// keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
let keyBoardRect = self.view.convert(keyboardScreenEndFrame, from:nil)
UIView.animate(withDuration: animationDuration, delay: 0, options: .beginFromCurrentState, animations: {
// Keyboard is going to appear. move composebar up
if showsKeyboard {
self.constraintBottomAttachmentView.constant = keyBoardRect.size.height
} else { // Keyboard is going to disappear. Move composebar down.
self.constraintBottomAttachmentView.constant = 0
}
self.view.layoutIfNeeded()
}, completion: { finished in
// Update the height of recipient bar.
self.updateRecipientBarMaxHeight()
})
}
将在某些情况下导致运行时错误,因为生成的类将没有有效的Java类名。