如何将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文章 。