如何在groovy脚本中包含jar? [重复]

时间:2023-01-13 16:04:24

This question already has an answer here:

这个问题在这里已有答案:

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。

9 个解决方案

#1


31  

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())

#2


44  

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 groovy issue, 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.

使用#!/ usr / bin / env groovy启动一个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 "$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开始运行并看到第一行。在bash中#是用于注释而//被折叠到/哪个是根目录。所以bash将运行/ usr / bin中/ env的常规-cp extra.jar:的spring.jar:etc.jar -d -Dlog4j.configuration =文件:/etc/myapp/log4j.xml “$ 0” $ @这将启动与常规我们所有的理由。 “$ 0”是我们脚本的路径,$ @是参数。现在groovy运行它忽略前两行并看到我们的groovy脚本然后退出回bash。然后bash退出(退出$?1),状态代码来自groovy。

#3


21  

You can add the jars to $HOME/.groovy/lib

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

#4


21  

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 Central Repository,下载引用的jar,然后将它放在类路径上。然后您可以像使用任何其他库一样使用该库。语法非常简单:

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

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存储库中。

#5


10  

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

#6


5  

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

#7


4  

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的解决方案以及适用于Linux和Cygwin的foozbar评论的组合:

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

How it works:

怎么运行的:

  • // is a valid groovy comment, so all of the bash commands are ignored by Groovy.
  • //是一个有效的groovy注释,因此Groovy会忽略所有bash命令。
  • // will return an error, but the error output is redirected to /dev/null and is therefore not displayed.
  • //将返回错误,但错误输出将重定向到/ dev / null,因此不会显示。
  • bash executes commands following a semicolon even though the previous command failed.
  • 即使前一个命令失败,bash也会按分号执行命令。
  • 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)
  • exec替换当前进程中的当前程序而不需要新进程。因此,groovy在原始脚本进程中运行(ps将进程显示为脚本而不是groovy可执行文件)
  • The exit $? statement following exec 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.
  • 退出$? exec groovy之后的语句阻止bash尝试将脚本的其余部分解释为bash脚本,并且还保留了groovy脚本的返回代码。

The above bash trick is more convenient in some cases than the RootLoader trick because 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技巧更方便,因为你可以在脚本中使用常规的import语句。使用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的解决方案可能会带来更好的性能,因为它们可以避免产生和丢失错误的开销。

#8


3  

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添加到类路径中,事情就会变得非常难以理解。但是你可以做到以下几点!

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

Let your imagination run wild on how complex a command line you can break down this way into manageable pieces

让你的想象力疯狂,你可以通过这种方式将命令行分解为可管理的部分

Maarten

马腾

#9


2  

If you want to use it right away before the import declarations it is possible like this :) :

如果你想在导入声明之前立即使用它,可以这样:):

// 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.

摘自这篇javaworld.com文章。

#1


31  

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())

#2


44  

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 groovy issue, 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.

使用#!/ usr / bin / env groovy启动一个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 "$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开始运行并看到第一行。在bash中#是用于注释而//被折叠到/哪个是根目录。所以bash将运行/ usr / bin中/ env的常规-cp extra.jar:的spring.jar:etc.jar -d -Dlog4j.configuration =文件:/etc/myapp/log4j.xml “$ 0” $ @这将启动与常规我们所有的理由。 “$ 0”是我们脚本的路径,$ @是参数。现在groovy运行它忽略前两行并看到我们的groovy脚本然后退出回bash。然后bash退出(退出$?1),状态代码来自groovy。

#3


21  

You can add the jars to $HOME/.groovy/lib

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

#4


21  

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 Central Repository,下载引用的jar,然后将它放在类路径上。然后您可以像使用任何其他库一样使用该库。语法非常简单:

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

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存储库中。

#5


10  

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

#6


5  

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

#7


4  

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的解决方案以及适用于Linux和Cygwin的foozbar评论的组合:

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

How it works:

怎么运行的:

  • // is a valid groovy comment, so all of the bash commands are ignored by Groovy.
  • //是一个有效的groovy注释,因此Groovy会忽略所有bash命令。
  • // will return an error, but the error output is redirected to /dev/null and is therefore not displayed.
  • //将返回错误,但错误输出将重定向到/ dev / null,因此不会显示。
  • bash executes commands following a semicolon even though the previous command failed.
  • 即使前一个命令失败,bash也会按分号执行命令。
  • 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)
  • exec替换当前进程中的当前程序而不需要新进程。因此,groovy在原始脚本进程中运行(ps将进程显示为脚本而不是groovy可执行文件)
  • The exit $? statement following exec 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.
  • 退出$? exec groovy之后的语句阻止bash尝试将脚本的其余部分解释为bash脚本,并且还保留了groovy脚本的返回代码。

The above bash trick is more convenient in some cases than the RootLoader trick because 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技巧更方便,因为你可以在脚本中使用常规的import语句。使用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的解决方案可能会带来更好的性能,因为它们可以避免产生和丢失错误的开销。

#8


3  

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添加到类路径中,事情就会变得非常难以理解。但是你可以做到以下几点!

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

Let your imagination run wild on how complex a command line you can break down this way into manageable pieces

让你的想象力疯狂,你可以通过这种方式将命令行分解为可管理的部分

Maarten

马腾

#9


2  

If you want to use it right away before the import declarations it is possible like this :) :

如果你想在导入声明之前立即使用它,可以这样:):

// 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.

摘自这篇javaworld.com文章。