web-dev-qa-db-ja.com

jarをgroovyスクリプトに含めるにはどうすればよいですか?

Jarにライブラリを必要とするグルーヴィーなスクリプトがあります。それをクラスパスに追加するにはどうすればよいですか?スクリプトを実行可能にしたいので、スクリプトの先頭で#!/usr/bin/env groovyを使用しています。

46
timdisney

本当に必要な場合は、実行時にJARをロードすることもできます。

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

#!/usr/bin/env groovyでgroovyスクリプトを開始することには非常に重要な制限があります-追加の引数は追加できません。クラスパスは設定できません。これは groovy の問題ではなく、Shebang(#!)の動作の制限です。追加の引数はすべて単一の引数として扱われるため、#!/usr/bin/env groovy -d/usr/bin/envgroovy -d rathenコマンドを実行し、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'

すべての魔法は最初の2行で発生します。最初の行は、これが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が実行され、最初の2行が無視され、groovyスクリプトが表示され、bashに戻ります。 bashは、groovyからのステータスコードで終了(exit $?1)します。

50
Patrick

Jarを$ HOME/.groovy/libに追加できます

23
Ove S

私のお気に入りの方法は、Groovy Grapesを使用することです。これらは、Maven Central Repositoryにアクセスし、参照されたjarをダウンロードして、クラスパスに配置します。その後、他のライブラリと同様にライブラリを使用できます。構文は本当に簡単です:

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

詳細を読むことができます こちら 。ここでの大きな利点の1つは、スクリプトを配布するときに依存関係を配布する必要がないことです。この方法の唯一の欠点は、JarがMavenリポジトリにある必要があることです。

23
Spina

Groovy Grapeを試すこともできます。アノテーションを使用してクラスパスを変更できます。現在は実験的ですが、かなりクールです。 docs.groovy-lang.org/.../grape を参照してください

10
Bob Herrmann

Javaの場合と同じです。

これは、MySQLステータス監視スクリプトの実行例です。 mysql.jarには、スクリプトstatus.groovyから呼び出すMySQLコネクターが含まれています。

groovy -cp mysql.jar status.groovy ct1

6
tessein

以下は、 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'

使い方:

  • //は有効なgroovyコメントであるため、bashコマンドはすべてGroovyによって無視されます。
  • //はエラーを返しますが、エラー出力は/dev/nullにリダイレクトされるため、表示されません。
  • bashは、前のコマンドが失敗した場合でも、セミコロンに続くコマンドを実行します。
  • execは、新しいプロセスをフォークすることなく、現在のプロセスの現在のプログラムを置き換えます。したがって、groovyは元のスクリプトプロセス内で実行されます(psは、プロセスをgroovy実行可能ファイルではなくスクリプトとして表示します)
  • exit $?に続くexec groovyステートメントは、bashがスクリプトの残りをbashスクリプトとして解釈しようとするのを防ぎ、groovyスクリプトからの戻りコードも保持します。

上記のbashトリックは、スクリプト内で通常のimportステートメントを使用できるため、 RootLoaderトリック よりも便利な場合があります。 RootLoaderトリックを使用すると、リフレクションを使用してすべてのクラスを強制的にロードできます。これは、JDBCドライバーをロードする必要がある場合など、状況によっては問題ありませんが、他の状況では不便です。

スクリプトがCygwinで決して実行されないことがわかっている場合、PatrickまたはMaarteenのソリューションを使用すると、エラーの生成と破棄のオーバーヘッドを回避できるため、パフォーマンスがわずかに向上する可能性があります。

4
Jim Hurne

@Patrickに彼の答えを追加したことは、私を大いに助けてくれました。最近、別のトリックを発見しました。

多数のjarをすべて1行でクラスパスに追加すると、事態はまったく読めなくなる可能性があります。しかし、次のことができます!

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

この方法で管理しやすい部分に分解できるコマンドラインの複雑さに想像力をかきたててください

マールテン

3

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

2