如何在groovy脚本中包含jar?

时间:2008-11-20 17:29:49

标签: java groovy jar classpath

我有一个groovy脚本需要jar中的库。如何将其添加到类路径?我希望脚本可执行,所以我在脚本的顶部使用#!/usr/bin/env groovy

9 个答案:

答案 0 :(得分:49)

使用#!/usr/bin/env groovy启动groovy脚本有一个非常重要的限制 - 无法添加其他参数。无法配置类路径,不使用定义或调试运行groovy。这不是groovy问题,而是shebang(#!)如何工作的限制 - 所有其他参数都被视为单个参数,因此#!/usr/bin/env groovy -d告诉/usr/bin/env运行命令groovy -d然后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开始运行并看到第一行。 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脚本然后退出回bashbash然后退出(exit $?1),状态代码来自groovy。

答案 1 :(得分:32)

如果你真的需要,你也可以在运行时加载JAR:

this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())

答案 2 :(得分:23)

我最喜欢的方法是使用Groovy Grapes。这些访问Maven Central Repository,下载引用的jar,然后将它放在类路径上。然后您可以像使用任何其他库一样使用库。语法非常简单:

@Grab(group='com.google.collections', module='google-collections', version='1.0')

您可以阅读更多详情here。这里的一个主要优点是,在分发脚本时不需要分发依赖项。这种方法的唯一缺点是Jar必须在Maven存储库中。

答案 3 :(得分:22)

您可以将罐子添加到$ HOME / .groovy / lib

答案 4 :(得分:10)

您还可以尝试Groovy Grape。它允许您使用注释来修改类路径。它的实验现在,但非常酷。见docs.groovy-lang.org/.../grape

答案 5 :(得分:6)

与在Java中一样。

这是运行MySQL状态监视脚本的示例。 mysql.jar包含我从脚本status.groovy调用的MySQL连接器。

groovy -cp mysql.jar status.groovy ct1

答案 6 :(得分:4)

以下是Patrick's solutionMaarteen Boekhold's solution和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技巧在某些情况下比the RootLoader trick更方便,因为您可以在脚本中使用常规导入语句。使用RootLoader技巧会强制您使用反射加载所有类。这在某些情况下很好(例如当你需要加载JDBC驱动程序时),但在其他情况下却不方便。

如果您知道您的脚本永远不会在Cygwin上执行,那么使用Patrick或Maarteen的解决方案可能会带来更好的性能,因为它们可以避免产生和丢失错误的开销。 / p>

答案 7 :(得分:3)

向@Patrick添加了他的答案,这对我帮助很大,我最近发现了另一个技巧。

如果在一行中将大量的jar添加到类路径中,事情就会变得非常难以理解。但是你可以做到以下几点!

#!/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"

让你的想象力在于你可以将命令行分解为可管理的部分的复杂程度

马腾

答案 8 :(得分:2)

如果您想在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 article