3 用法
3.1 注释
可以在任何位置添加一个或多个 groovy.lang.Grab
注释,它们会告诉编译器代码所依赖的某个具体库。这和把库添加到 Groovy 编译器的类路径上的作用是一样的。在脚本中,这种注释会在任何其他类解析之前被发现并执行,所以导入类可以通过 @Grab
正确地得到解析。
import com.jidesoft.swing.JideSplitButton
@Grab(group='com.jidesoft', module='jide-oss', version='[2.2.1,2.3.0)')
public class TestClassAnnotation {
public static String testMethod () {
return JideSplitButton.class.name
}
}
含有类(或者在注释脚本元素情况下的脚本类)的类静态初始化器会正确地调用 grab(…)
。
3.2 多重 Grape 注释
为了在同一节点多次使用 Grape 注释,必须使用 @Grapes
,如下所示:
@Grapes([
@Grab(group='commons-primitives', module='commons-primitives', version='1.0'),
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='0.9.7')])
class Example {
// ...
}
否则,就会出现下列错误:
Cannot specify duplicate annotation on the same member
3.3 方法调用
通常对 grab 的调用往往发生在脚本或类初始化这种早期阶段。这是为了确保在 Groovy 代码依赖库代码前,库可以被类加载器所利用。典型的调用如下所示:
import groovy.grape.Grape
// 随机 maven 库
Grape.grab(group:'com.jidesoft', module:'jide-oss', version:'[2.2.0,)')
Grape.grab([group:'org.apache.ivy', module:'ivy', version:'2.0.0-beta1', conf:['default', 'optional']],
[group:'org.apache.ant', module:'ant', version:'1.7.0'])
- 在相同上下文中,参数也相同时,多次对 grab 调用应该是幂等(idempotent)的。但如果同样的代码在不同的
ClassLoader
上下文中调用时,解析就会重新运行。 - 如果传入
grab
中的args
映射拥有预定为 true 的noExceptions
属性,则不会抛出异常。 grab
需要在调用类的ClassLoader
链中指定或存在grab
或RootLoader
。默认,如果这样一种ClassLoader
无法获得,则会反映在模块解析上,就会抛出异常:- 通过
classLoader:
参数传入的类加载器,及其父级类加载器; - 作为
referenceObject:
参数传入的类加载器,及其父级类加载器; - 发出对
grab
调用的类的类加载器。
- 通过
3.3.1 grab(HashMap) 参数
group:
-\<字符串型>-模块来自的模块组。直接转换为 Maven groupId。任何匹配/groovy(|\..|x|x\..)/
的模块组都被保留下来,可能对 Groovy 支持模块而言有特殊含义。module:
-\<字符串型>-要加载的模块名称。直接转换为 Maven artifactId。version:
-\<字符串型>,有可能是\-所要使用模块的版本。无论是字面版本 '1.1-RC3' 还是 Ivy 范围 '[2.2.1,]',都表示 2.2.1 或更新的版本。classifier:
-\<字符串型>-解析所利用的 Maven 分类器。conf:
-\<字符串型>默认为 'default'-意指想要下载的模块的配置或范围,映射至runtime
和master
范围。force:
-\<布尔类型>默认为 true-用于表明该版本必须用在发生冲突的情况下,与冲突管理器无关。changing:
-\<布尔类型>默认为 false-是否无需版本名称改变,就能改变工件。transitive:
-\<布尔类型>默认为 true-是否解决该模块的其他依赖项。
grab
有两大主要变体,一个带有单一的映射,另一个则带有一个参数映射及多个依赖映射。调用单一映射的 grab 和调用传入两次映射的 grab 完全相同,所以 grab 的参数和依赖项都可以混合在一个单独的映射中,grab 可以作为带有多个已命名参数的单一方法进行调用。
这些参数有以下这些同义词,然而提交多个会造成运行时异常。
group:
、groupId:
、organisation:
、organization:
、org:
module:
、artifactId:
、artifact:
version:
、revision:
、rev:
conf:
、scope:
、configuration:
3.3.2 参数映射的参数
classLoader:
-\<GroovyClassLaoder> 或 \<RootClassLoader> - 添加要解析的 jar 的类加载器。refObject:
-\<Object>-对象类所用的最近的父级类加载器会被作为,尽管传入的是classLoader
。validate:
-\<布尔类型>默认为 false-是否验证 pom 或 ivy 文件(true),或者相信缓存(false)。noExceptions:
-\<布尔类型>默认为 false-如果类加载器解析或仓库查询失败,是否抛出异常(false)或静默失败(true)。
3.4 命令行工具
Grape 添加了一个命令行可执行的 grape
,从而实现对本地 grape 缓存的检查与管理。
grape install <groupId> <artifactId> [<version>]
该命令会安装指定的 Groovy 模块或 Maven 工件。如果指定的是特定的版本,则会安装该版本;如未指定,则安装最新的版本(就好像我们用的是 *
)。
grape list
列出本地安装模块(Groovy 模块则要带上它们的完整的 maven 名称)及版本。
grape resolve (<groupId> <artifactId> <version>)+
这将返回 jar 文件的位置,它代表指定模块及相应传递依赖的工件。还可以选择性地传入 -ant
、 -dos
或 -shell
,获取用 ant 脚本、Windows 批处理文件以及 Unix Shell 脚本的格式表达的依赖。也可以传入 -ivy
,查看用类似 ivy 格式表达的依赖。
3.5 高级配置
3.5.1 仓库目录
如果需要改变 grape 用来下载库的目录,可以指定 grape.root 系统属性来改变默认配置(~/.groovy/grape)。
groovy -Dgrape.root=/repo/grape yourscript.groovy
3.5.2 自定义 Ivy 设置
可以通过创建一个 ~/.groovy/grapeConfig.xml 文件来自定义 Grape 所使用的 ivy 设置。如果不存在这种文件,可以参考一下 Grape 使用的默认设置 。
关于自定义设置的详细信息,可参考 Ivy 文档 。
3.6 更多范例
使用 Apache Commons 集合库:
// 创建并使用原始数组列表
import org.apache.commons.collections.primitives.ArrayIntList
@Grab(group='commons-primitives', module='commons-primitives', version='1.0')
def createEmptyInts() { new ArrayIntList() }
def ints = createEmptyInts()
ints.add(0, 42)
assert ints.size() == 1
assert ints.get(0) == 42
使用 TagSoup:
// 寻找 Java 规范的 PDF 链接
@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2.1')
def getHtml() {
def parser = new XmlParser(new org.ccil.cowan.tagsoup.Parser())
parser.parse("https://docs.oracle.com/javase/specs/")
}
html.body.'**'.a.@href.grep(~/.*\.pdf/).each{ println it }
使用 Google 集合库:
import com.google.common.collect.HashBiMap
@Grab(group='com.google.code.google-collections', module='google-collect', version='snapshot-20080530')
def getFruit() { [grape:'purple', lemon:'yellow', orange:'orange'] as HashBiMap }
assert fruit.lemon == 'yellow'
assert fruit.inverse().yellow == 'lemon'
启动 Jetty 服务器为 Groovy 模板提供服务:
@Grapes([
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-server', version='8.1.7.v20120910'),
@Grab(group='org.eclipse.jetty.aggregate', module='jetty-servlet', version='8.1.7.v20120910'),
@Grab(group='javax.servlet', module='javax.servlet-api', version='3.0.1')])
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.*
import groovy.servlet.*
def runServer(duration) {
def server = new Server(8080)
def context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
context.resourceBase = "."
context.addServlet(TemplateServlet, "*.gsp")
server.start()
sleep duration
server.stop()
}
runServer(10000)
一加载脚本,Grape 就会下载 Jetty 及其依赖,并予以缓存。我们在 8080 端口处创建新的 Jetty 服务器,然后在上下文的根目录暴露 Groovy 的 TemplateServlet —— Groovy 自带一个功能强大的模板引擎机制。启动服务器,让它运行一段时间。每当点击 http://localhost:8080/somepage.gsp 时,就会显示 somepage.gsp 模板。这些模板页面应该和服务器脚本同位于一个目录。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论