我有一段 Groovy 脚本,需要使用一个 Jar 包中的库。如何将其添加到类路径(classpath)中?我希望该脚本是可执行的,因此在脚本顶部使用了 #!/usr/bin/env groovy
。
#!/usr/bin/env groovy
开始的Groovy脚本有一个非常重要的限制 - 不能添加额外的参数。 无法配置classpath,无法使用定义或调试运行Groovy。这不是groovy问题,而是shebang (#!
)工作方式的限制 - 所有其他参数都被视为单个参数,因此#!/usr/bin/env groovy -d
告诉/usr/bin/env
运行命令groovy -d
而不是带有d
参数的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'
// 2>/dev/null; SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"; exec groovy -cp "$SCRIPT_DIR" "$0"
- foozbar如果您确实需要,也可以在运行时加载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目录下。
#!/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 忽略。//
会返回错误,但错误输出被重定向到 /dev/null
,因此不会显示。exec
替换当前进程中的当前程序,而不是分叉出一个新进程。因此,groovy 在原始脚本进程内运行(ps
显示的进程为脚本而不是 groovy 可执行文件)。exec groovy
后面的 exit $?
语句防止 bash 尝试将剩余的脚本解释为 bash 脚本,并保留 groovy 脚本的返回代码。上述 bash 技巧在某些情况下比 RootLoader 技巧 更方便,因为您可以在脚本中使用常规导入语句。使用 RootLoader 技巧会强制您使用反射加载所有类。这在某些情况下很好(例如当您需要加载 JDBC 驱动程序时),但在其他情况下不方便。
如果您知道您的脚本永远不会在Cygwin上执行,那么使用Patrick或Maarteen的解决方案可能会导致稍微更好的性能,因为它们避免了生成和丢弃错误的开销。
和在Java中一样。
这是运行MySQL状态监控脚本的示例。mysql.jar包含了MySQL连接器,我从脚本status.groovy中调用它。
groovy -cp mysql.jar status.groovy ct1
-cp mysql.jar
无法正常工作。相反,我必须使用-cp ./mysql.jar
。 - Kirill除了@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"
让你的想象力自由发挥,想象一下你可以将多么复杂的命令行分解成易于处理的部分。
马尔滕
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}."
}
Taken from this javaworld.com article.
#!/bin/sh
,然后使用您想要的任何参数调用groovy
。 最小化将是#!/bin/sh\n groovy -cp PATH-OR-JAR $@
,以将传递给命令行的所有参数传递给 groovy 命令。 在 Windows 中,它将是groovy -cp PATH %*
。 - PatS