我有一个groovy脚本需要jar中的库.如何将其添加到类路径?我希望脚本可执行,所以我#!/usr/bin/env groovy
在脚本的顶部使用.
启动groovy脚本#!/usr/bin/env groovy
具有非常重要的限制 - 不能添加其他参数.没有类路径可以配置,没有定义或在调试中运行groovy.这不是一个常规问题,而是对shebang(#!
)如何工作的限制- 所有其他参数都被视为单个参数,因此#!/usr/bin/env groovy -d
告诉/usr/bin/env
运行命令groovy -d
rathen然后groovy
使用参数d
.
这个问题有一个解决方法,包括在groovy脚本中使用bash引导groovy .
#!/bin/bash //usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" $@; exit $? import org.springframework.class.from.jar //other groovy code println 'Hello'
所有的魔力都发生在前两行.第一行告诉我们这是一个bash
脚本.bash
开始运行并看到第一行.In bash
#
用于注释,//
并折叠到/
根目录.因此bash
将运行/usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" $@
以所有我们想要的参数开始groovy.这"$0"
是我们脚本的路径,$@
也是参数.现在groovy运行它忽略前两行并看到我们的groovy脚本然后退出回来bash
.bash
然后exit $?1
使用来自groovy的状态代码退出().
如果您真的需要,还可以在运行时加载JAR:
this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())
我最喜欢的方法是使用Groovy Grapes.这些访问Maven Central Repository,下载引用的jar,然后将它放在类路径上.然后您可以像使用任何其他库一样使用库.语法非常简单:
@Grab(group='com.google.collections', module='google-collections', version='1.0')
你可以在这里阅读更多细节.这里的一个主要优点是,在分发脚本时不需要分发依赖项.这种方法的唯一缺点是Jar必须在Maven存储库中.
您可以将jar添加到$ HOME/.groovy/lib
您还可以尝试Groovy Grape.它允许您使用注释来修改类路径.它的实验现在,但非常酷.见docs.groovy-lang.org/.../grape
和你在Java中一样.
这是运行MySQL状态监视脚本的示例.mysql.jar包含我从脚本status.groovy调用的MySQL连接器.
groovy -cp mysql.jar status.groovy ct1
以下是Patrick的解决方案,Maarteen Boekhold的解决方案和foozbar的注释(可在Linux和Cygwin上使用)的组合:
#!/bin/bash // 2>/dev/null; SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" // 2>/dev/null; OPTS="-cp $SCRIPT_DIR/lib/extra.jar:$SCRIPT_DIR/lib/spring.jar" // 2>/dev/null; OPTS="$OPTS -d" // 2>/dev/null; OPTS="$OPTS -Dlog4j.configuration=file:/etc/myapp/log4j.xml" // 2>/dev/null; exec groovy $OPTS "$0" "$@"; exit $? import org.springframework.class.from.jar //other groovy code println 'Hello'
怎么运行的:
//
是有效的groovy注释,因此Groovy会忽略所有bash命令。
//
将返回一个错误,但是错误输出被重定向到/dev/null
,因此不会显示。
即使前一个命令失败,bash也会在分号后执行命令。
exec
替换当前进程中的当前程序,而不派生新进程。因此,groovy在原始脚本进程中运行(ps
将进程显示为脚本而不是groovy可执行文件)
以下exit $?
语句exec groovy
防止bash尝试将脚本的其余部分解释为bash脚本,并且还保留了groovy脚本的返回代码。
在某些情况下,上述bash技巧比RootLoader技巧更方便,因为您可以在脚本中使用常规的import语句。使用RootLoader技巧会强制您使用反射来加载所有类。在某些情况下(例如,当您需要加载JDBC驱动程序时),这很好,但在其他情况下,则很不方便。
如果您知道您的脚本永远不会在Cygwin上执行,那么使用Patrick或Maarteen的解决方案可能会导致性能略有提高,因为它们避免了产生和丢弃错误的开销。