我有一个groovy脚本需要jar中的库。如何将其添加到类路径?我希望脚本可执行,所以我在脚本的顶部使用#!/usr/bin/env groovy
。
答案 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脚本然后退出回bash
。 bash
然后退出(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 solution,Maarteen 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
,因此不会显示。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}."
}