J'ai un script groovy qui a besoin d'une bibliothèque dans un bocal. Comment ajouter cela au chemin de classe? Je veux que le script soit exécutable, donc j'utilise #!/usr/bin/env groovy
en haut de mon script.
Si vous en avez vraiment besoin, vous pouvez également charger un JAR au moment de l'exécution avec:
this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())
Démarrer un script groovy avec #!/usr/bin/env groovy
a une limitation très importante - Aucun argument supplémentaire ne peut être ajouté. Aucun chemin de classe ne peut être configuré, aucun groovy en cours d'exécution avec define ou en débogage. Ce n'est pas un problème groovy , mais une limitation de la façon dont le Shebang (#!
) fonctionne - tous les arguments supplémentaires sont traités comme un seul argument donc #!/usr/bin/env groovy -d
raconte /usr/bin/env
pour exécuter la commande groovy -d
rathen puis groovy
avec un argument de d
.
Il existe une solution de contournement pour le problème, qui implique le démarrage de groovy avec bash dans le script 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'
Toute la magie opère dans les deux premières lignes. La première ligne nous indique qu'il s'agit d'un script bash
. bash
démarre et voit la première ligne. Dans bash
#
est pour les commentaires et //
est réduit à /
qui est le répertoire racine. bash
s'exécutera donc /usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" $@
qui commence groovy avec tous nos arguments souhaités. Le "$0"
est le chemin vers notre script, et $@
sont les arguments. Maintenant groovy s'exécute et il ignore les deux premières lignes et voit notre script groovy, puis revient à bash
. bash
puis quitte (exit $?1
) avec le code d'état de groovy.
Vous pouvez ajouter les pots dans $ HOME/.groovy/lib
Ma façon préférée de le faire est avec Groovy Grapes. Ceux-ci accèdent au référentiel central Maven, téléchargent le pot référencé, puis le placent sur le chemin de classe. Ensuite, vous pouvez utiliser la bibliothèque comme n'importe quelle autre bibliothèque. La syntaxe est vraiment simple:
@Grab(group='com.google.collections', module='google-collections', version='1.0')
Vous pouvez lire plus de détails ici . Un avantage majeur ici est que vous n'avez pas besoin de distribuer vos dépendances lorsque vous distribuez votre script. Le seul inconvénient de cette méthode est que le Jar doit être dans le référentiel Maven.
Vous pouvez également essayer Groovy Grape. Il vous permet d'utiliser des annotations pour modifier le chemin de classe. C'est expérimental en ce moment, mais plutôt cool. Voir docs.groovy-lang.org/.../grape
Comme vous le feriez en Java.
Ceci est un exemple d'exécution d'un script de surveillance d'état MySQL. mysql.jar contient le connecteur MySQL que j'appelle depuis le script status.groovy.
groovy -cp mysql.jar status.groovy ct1
Voici une combinaison de la solution de Patrick , la solution de Maarteen Boekhold , et le commentaire de foozbar qui fonctionne à la fois avec Linux et 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'
Comment ça marche:
//
est un commentaire groovy valide, donc toutes les commandes bash sont ignorées par Groovy.//
renverra une erreur, mais la sortie d'erreur est redirigée vers /dev/null
et n'est donc pas affiché.exec
remplace le programme en cours dans le processus en cours sans bifurquer un nouveau processus. Ainsi, groovy s'exécute dans le processus de script d'origine (ps
montre le processus comme le script plutôt que l'exécutable groovy)exit $?
instruction suivant exec groovy
empêche bash d'essayer d'interpréter le reste du script comme un script bash et préserve également le code retour du script groovy.L'astuce bash ci-dessus est plus pratique dans certains cas que l'astuce RootLoader car vous pouvez utiliser des instructions d'importation régulières dans le script. L'utilisation de l'astuce RootLoader vous oblige à charger toutes les classes à l'aide de la réflexion. C'est très bien dans certaines situations (comme lorsque vous devez charger un pilote JDBC), mais pas pratique dans d'autres.
Si vous savez que votre script ne sera jamais exécuté sur Cygwin, alors l'utilisation de la solution de Patrick ou de Maarteen entraînera probablement des performances légèrement meilleures car elles évitent la surcharge de génération et d'élimination d'une erreur.
En ajoutant à @Patrick sa réponse, qui m'a beaucoup aidé, j'ai récemment découvert un autre truc.
Si vous ajoutez beaucoup de pots au chemin de classe sur une seule ligne, les choses peuvent devenir tout à fait illisibles. Mais vous pouvez faire ce qui suit!
#!/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"
Laissez libre cours à votre imagination sur la complexité d'une ligne de commande que vous pouvez décomposer de cette façon en éléments gérables
Maarten
Si vous voulez l'utiliser tout de suite avant les déclarations import
c'est possible comme ceci :):
// 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}."
}
Tiré de cela article javaworld.com .