如何将jar包包含在groovy脚本中?
我有一个groovy脚本需要在一个jar子里的图书馆。 我如何将其添加到类path? 我希望脚本是可执行的,所以我在脚本的顶部使用#!/usr/bin/env groovy
。
如果你真的需要,你也可以在运行时加载一个JAR:
this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())
使用#!/usr/bin/env groovy
启动groovy脚本有一个非常重要的限制 – 不能添加额外的参数。 没有classpath可以configuration,没有定义或在debugging运行groovy。 这不是一个常规的问题,但在shebang( #!
)的工作方式上有一个限制 – 所有附加的参数都被当作单一的参数,所以#!/usr/bin/env groovy -d
告诉/usr/bin/env
运行那么这个命令就会随着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
开始运行并看到第一行。 在bash
#
是用于注释和/
被折叠到/
哪个是根目录。 所以bash
会运行/usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" $@
开始groovy与所有我们想要的论点。 "$0"
是我们脚本的path, $@
是参数。 现在groovy运行,它忽略了前两行,看到我们的groovy脚本,然后退出到bash
。 然后bash
退出( exit $?1
)与groovy的状态代码。
您可以将这些jar子添加到$ HOME / .groovy / lib
我最喜欢的方式是使用Groovy Grapes。 这些访问Maven Central Repository,下载引用的jar,然后放到classpath中。 然后,您可以像使用其他库一样使用该库。 语法非常简单:
@Grab(group='com.google.collections', module='google-collections', version='1.0')
你可以在这里阅读更多细节。 这里的一个主要优点是在分发脚本时不需要分配依赖关系。 这个方法唯一的缺点是Jar必须在Maven仓库中。
你也可以尝试Groovy葡萄。 它允许您使用注释来修改类path。 它的实验现在,但很酷。 请参阅http://groovy.codehaus.org/Grape
和你在Java中一样。
这是运行MySQL状态监视脚本的一个例子。 mysql.jar包含我从脚本status.groovy调用的MySQL连接器。
groovy -cp mysql.jar status.groovy ct1
他的回答给@帕特里克增加了很多,最近我发现了另外一个窍门。
如果你把大量的jar添加到classpath中,那么事情会变得很难理解。 但是你可以做以下的事情!
#!/bin/bash //bin/true && OPTS="-cp blah.jar -Dmyopt=value" //bin/true && OPTS="$OPTS -Dmoreopts=value2" //usr/bin/env groovy $OPTS "$0" $@; exit $? println "inside my groovy script"
让你的想象力疯狂在命令行的复杂程度上,你可以把它分解成可pipe理的部分
马腾
下面是Patrick的解决scheme , Maarteen Boekhold的解决scheme和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注释,所以所有的bash命令都被Groovy忽略。 -
//
将返回一个错误,但错误输出被redirect到/dev/null
,因此不会显示。 - 即使前面的命令失败,bash也会在分号之后执行命令。
-
exec
取代当前进程中的当前程序,而不需要分配新的进程。 因此,Groovy在原始脚本进程中运行(ps
将进程显示为脚本而不是groovy可执行文件) -
exit $?
exec groovy
语句阻止bash尝试将脚本的其余部分解释为bash脚本,并保留groovy脚本的返回码。
在某些情况下,上述bash技巧比RootLoader技巧更方便,因为您可以在脚本中使用常规导入语句。 使用RootLoader技巧迫使你使用reflection来加载所有的类。 在某些情况下(例如,当您需要加载JDBC驱动程序时),这很好,但在其他情况下不方便。
如果您知道您的脚本永远不会在Cygwin上执行,那么使用Patrick或Maarteen的解决scheme可能会导致稍微好一点的性能,因为它们避免了生成和抛出错误的开销。
如果你想在import
声明之前马上使用它,可以像这样:)
// printEmployees.groovy this.class.classLoader.rootLoader.addURL( new URL("file:///C:/app/Dustin/product/11.1.0/db_1/jdbc/lib/ojdbc6.jar")) import groovy.sql.Sql sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:orcl", "hr", "hr", "oracle.jdbc.pool.OracleDataSource") sql.eachRow("SELECT employee_id, last_name, first_name FROM employees") { println "The employee's name is ${it.first_name} ${it.last_name}." }
采取从这个javaworld.com文章 。