Java 如何在 groovy 脚本中包含 jars?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/306139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I include jars in a groovy script?
提问by timdisney
I have a groovy script that needs a library in a jar. How do I add that to the classpath? I want the script to be executable so I'm using #!/usr/bin/env groovy
at the top of my script.
我有一个 groovy 脚本,需要一个 jar 中的库。如何将其添加到类路径?我希望脚本是可执行的,所以我#!/usr/bin/env groovy
在脚本的顶部使用。
采纳答案by Eric Wendelin
If you really have to you can also load a JAR at runtime with:
如果你真的需要,你也可以在运行时加载一个 JAR:
this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())
回答by tessein
The same as you would in Java.
与在 Java 中一样。
This is an example of running a MySQL status monitoring script. mysql.jar contains the MySQL connector that I call from script status.groovy.
这是运行 MySQL 状态监控脚本的示例。mysql.jar 包含我从脚本 status.groovy 调用的 MySQL 连接器。
groovy -cp mysql.jar status.groovy ct1
groovy -cp mysql.jar status.groovy ct1
回答by Ove S
You can add the jars to $HOME/.groovy/lib
您可以将罐子添加到 $HOME/.groovy/lib
回答by Bob Herrmann
You can also try out Groovy Grape. It lets you use annotations to modify the classpath. Its experimental right now, but pretty cool. See docs.groovy-lang.org/.../grape
您还可以试用 Groovy Grape。它允许您使用注释来修改类路径。它现在是实验性的,但很酷。请参阅docs.groovy-lang.org/.../grape
回答by Patrick
Starting a groovy script with #!/usr/bin/env groovy
has a very important limitation - No additional arguments can be added.No classpath can be configured, no running groovy with defines or in debug. This is not a groovyissue, but a limitation in how the shebang (#!
) works - all additional arguments are treated as single argument so #!/usr/bin/env groovy -d
is telling /usr/bin/env
to run the command groovy -d
rathen then groovy
with an argument of d
.
启动一个 groovy 脚本#!/usr/bin/env groovy
有一个非常重要的限制 -不能添加额外的参数。不能配置类路径,不能使用定义或调试运行 groovy。这不是一个常规问题,而是 shebang ( #!
) 工作方式的限制- 所有附加参数都被视为单个参数,因此#!/usr/bin/env groovy -d
告诉/usr/bin/env
运行命令groovy -d
rathen groovy
,参数为d
。
There is a workaround for the issue, which involves bootstrapping groovy with bash in the groovy script.
该问题有一个解决方法,它涉及在 groovy 脚本中使用 bash 引导 groovy 。
#!/bin/bash
//usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "@Grab(group='com.google.collections', module='google-collections', version='1.0')
" $@; exit $?
import org.springframework.class.from.jar
//other groovy code
println 'Hello'
All the magic happens in the first two lines. The first line tells us that this is a bash
script. bash
starts running and sees the first line. In bash
#
is for comments and //
is collapsed to /
which is the root directory. So bash
will run /usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" $@
which starts groovy with all our desired arguments. The "$0"
is the path to our script, and $@
are the arguments. Now groovy runs and it ignores the first two lines and sees our groovy script and then exits back to bash
. bash
then exits (exit $?1
) with status code from groovy.
所有的魔法都发生在前两行。第一行告诉我们这是一个bash
脚本。bash
开始运行并看到第一行。Inbash
#
用于评论并//
折叠到/
哪个是根目录。So bash
will run/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 的状态代码退出 ( )。
回答by Spina
My Favorite way to do this is with Groovy Grapes. These access the Maven Central Repository, download the referenced jar, and then put it on the classpath. Then you can use the library like any other library. The syntax is really simple:
我最喜欢的方法是使用 Groovy Grapes。这些访问 Maven 中央存储库,下载引用的 jar,然后将其放在类路径中。然后您可以像使用任何其他库一样使用该库。语法非常简单:
#!/bin/bash
//bin/true && OPTS="-cp blah.jar -Dmyopt=value"
//bin/true && OPTS="$OPTS -Dmoreopts=value2"
//usr/bin/env groovy $OPTS "#!/bin/bash
// 2>/dev/null; SCRIPT_DIR="$( cd "$( dirname "// 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}."
}
" )" && 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 "##代码##" "$@"; exit $?
import org.springframework.class.from.jar
//other groovy code
println 'Hello'
" $@; exit $?
println "inside my groovy script"
You can read more details here. One major advantage here is that you don't need to distribute your dependencies when you distribute your script. The only drawback to this method is that the Jar has to be in the Maven repository.
您可以在此处阅读更多详细信息。这里的一个主要优点是,在分发脚本时不需要分发依赖项。这种方法的唯一缺点是 Jar 必须在 Maven 存储库中。
回答by Maarten Boekhold
Adding to @Patrick his answer, which helped me a lot, I recently discovered another trick.
加上@Patrick 他的回答,这对我帮助很大,我最近发现了另一个技巧。
If you add lots of jars to the classpath all on one line, things can become quite unreadable. But you can do the following!
如果您在一行中向类路径中添加大量 jar,事情可能会变得非常难以理解。但是你可以做到以下几点!
##代码##Let your imagination run wild on how complex a command line you can break down this way into manageable pieces
让您的想象力在命令行的复杂程度上尽情发挥,您可以通过这种方式将其分解为可管理的部分
Maarten
马丁
回答by Jim Hurne
Below is a combination of Patrick's solution, Maarteen Boekhold's solution, and foozbar's comment that works with both Linux and Cygwin:
下面是Patrick 的解决方案、Maarteen Boekhold 的解决方案和 foozbar 的评论的组合,适用于 Linux 和 Cygwin:
##代码##How it works:
这个怎么运作:
//
is a valid groovy comment, so all of the bash commands are ignored by Groovy.//
will return an error, but the error output is redirected to/dev/null
and is therefore not displayed.- bash executes commands following a semicolon even though the previous command failed.
exec
replaces the current program in the current process without forking a new process. Thus, groovy runs within the original script process (ps
shows the process as the script rather than the groovy executable)- The
exit $?
statement followingexec groovy
prevents bash from trying to interpret the rest of the script as a bash script, and also preserves the return code from the groovy script.
//
是有效的 groovy 注释,因此 Groovy 会忽略所有 bash 命令。//
将返回错误,但错误输出被重定向到/dev/null
并因此不显示。- 即使前一个命令失败,bash 也会在分号后执行命令。
exec
在不分叉新进程的情况下替换当前进程中的当前程序。因此,groovy 在原始脚本进程中运行(ps
将进程显示为脚本而不是 groovy 可执行文件)- 以下
exit $?
语句exec groovy
可防止 bash 尝试将脚本的其余部分解释为 bash 脚本,并且还保留了来自 groovy 脚本的返回代码。
The above bash trick is more convenient in some cases than the RootLoader trickbecause you can use regular import statements within the script. Using the RootLoader trick forces you to load all of the classes using reflection. This is fine in some situations (such as when you need to load a JDBC driver), but inconvenient in others.
在某些情况下,上述 bash 技巧比RootLoader 技巧更方便,因为您可以在脚本中使用常规导入语句。使用 RootLoader 技巧会强制您使用反射加载所有类。这在某些情况下很好(例如当您需要加载 JDBC 驱动程序时),但在其他情况下不方便。
If you know your script will never be executed on Cygwin, then using Patrick's or Maarteen's solution will likely result in slightly better performance because they avoid the overhead of generating and throwing away an error.
如果您知道您的脚本永远不会在 Cygwin 上执行,那么使用 Patrick 或 Maarteen 的解决方案可能会稍微提高性能,因为它们避免了生成和丢弃错误的开销。
回答by Andreas Dietrich
If you want to use it right away before the import
declarationsit is possible like this :) :
如果您想在import
声明之前立即使用它,则可能像这样:):
Taken from this javaworld.com article.
摘自这篇javaworld.com 文章。