J’ai lu comment importer simplement un fichier groovy dans un autre script groovy
Je veux définir des fonctions communes dans un fichier groovy et appeler ces fonctions à partir d’autres fichiers groovy.
Je comprends que cela utiliserait Groovy comme un langage de script, c’est-à-dire que je n’ai pas besoin de classes / d’objects. J’essaye de faire quelque chose comme dsl qui peut être fait dans groovy. Toutes les variables seront validées à partir de Java et je veux exécuter un script groovy dans un shell.
Est-ce possible ? Quelqu’un peut-il donner un exemple.
evaluate(new File("../tools/Tools.groovy"))
Mettez cela en haut de votre script. Cela apportera le contenu d’un fichier groovy (remplacez simplement le nom du fichier entre les guillemets avec votre script groovy).
Je le fais avec une classe appelée étonnamment “Tools.groovy”.
À partir de Groovy 2.2, il est possible de déclarer une classe de script de base avec la nouvelle annotation de transformation AST @BaseScript
.
Exemple:
fichier MainScript.groovy :
abstract class MainScript extends Script { def meaningOfLife = 42 }
fichier test.groovy :
import groovy.transform.BaseScript @BaseScript MainScript mainScript println "$meaningOfLife" //works as expected
Une autre façon de faire est de définir les fonctions dans une classe groovy et d’parsingr et d’append le fichier au classpath au moment de l’exécution:
File sourceFile = new File("path_to_file.groovy"); Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile); GroovyObject myObject = (GroovyObject) groovyClass.newInstance();
Je pense que le meilleur choix est d’organiser les utilitaires sous forme de classes groovy, de les append à classpath et de laisser le script principal s’y référer via le mot-clé import.
Exemple:
scripts / DbUtils.groovy
class DbUtils{ def save(something){...} }
scripts / script1.groovy:
import DbUtils def dbUtils = new DbUtils() def something = 'foobar' dbUtils.save(something)
script en cours d’exécution:
cd scripts groovy -cp . script1.groovy
Groovy n’a pas de mot-clé d’importation comme les langages de script typiques qui feront un littéral inclus du contenu d’un autre fichier (mentionné ici: groovy fournit-il un mécanisme d’inclusion? ).
En raison de sa nature orientée object / classe, vous devez “jouer à des jeux” pour faire des choses comme ce travail. Une possibilité est de rendre toutes les fonctions de votre utilitaire statiques (puisque vous avez dit qu’elles n’utilisent pas d’objects), puis d’effectuer une importation statique dans le contexte de votre shell d’exécution. Ensuite, vous pouvez appeler ces méthodes comme “fonctions globales”.
Une autre possibilité consisterait à utiliser un object Binding ( http://groovy.codehaus.org/api/groovy/lang/Binding.html ) lors de la création de votre Shell et de la liaison de toutes les fonctions souhaitées aux méthodes (l’inconvénient ici serait d’avoir énumérer toutes les méthodes de la liaison, mais vous pourriez peut-être utiliser la reflection). Une autre solution serait de remplacer methodMissing(...)
dans l’object delegate assigné à votre shell, ce qui vous permet de faire une dissortingbution dynamic en utilisant une carte ou la méthode de votre choix.
Plusieurs de ces méthodes sont présentées ici: http://www.nextinstruction.com/blog/2012/01/08/creating-dsls-with-groovy/ . Faites-moi savoir si vous voulez voir un exemple d’une technique particulière.
La façon dont je fais cela est avec GroovyShell
.
GroovyShell shell = new GroovyShell() def Util = shell.parse(new File('Util.groovy')) def data = Util.fetchData()
Voici un exemple complet d’inclusion d’un script dans un autre.
Il suffit de lancer le fichier Testmain.groovy
Commentaires explicatifs inclus parce que je suis gentil comme ça;]
Testutils.groovy
// This is the 'include file' // Testmain.groovy will load it as an implicit class // Each method in here will become a method on the implicit class def myUtilityMethod(Ssortingng msg) { println "myUtilityMethod running with: ${msg}" }
Testmain.groovy
// Run this file // evaluate implicitly creates a class based on the filename specified evaluate(new File("./Testutils.groovy")) // Safer to use 'def' here as Groovy seems fussy about whether the filename (and therefore implicit class name) has a capital first letter def tu = new Testutils() tu.myUtilityMethod("hello world")
Que diriez-vous de traiter le script externe comme une classe Java? Basé sur cet article: https://www.jmdawson.net/blog/2014/08/18/using-functions-from-one-groovy-script-in-another/
getThing.groovy Le script externe
def getThingList() { return ["thing","thin2","thing3"] }
printThing.groovy Le script principal
thing = new getThing() // new the class which represents the external script println thing.getThingList()
Résultat
$ groovy printThing.groovy [thing, thin2, thing3]
Pour les plus récents, il semble que groovy supporte maintenant la commande :load file-path
qui redirige simplement les entrées du fichier donné, il est donc désormais facile d’inclure des scripts de bibliothèque.
Il fonctionne comme une entrée dans le groovysh & comme une ligne dans un fichier chargé:
groovy:000> :load file1.groovy
file1.groovy peut contenir:
:load path/to/another/file invoke_fn_from_file();
Une combinaison de réponses @grahamparks et @snowindy avec quelques modifications est ce qui a fonctionné pour mes scripts Groovy exécutés sur Tomcat:
Utils.groovy
class Utils { def doSth() {...} }
MyScript.groovy:
/* import Utils --> This import does not work. The class is not even defined at this time */ Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(new File("full_path_to/Utils.groovy")); // Otherwise it assumes current dir is $CATALINA_HOME def foo = groovyClass.newInstance(); // 'def' solves comstack time errors!! foo.doSth(); // Actually works!
Après quelques investigations, je suis arrivé à la conclusion que l’approche suivante semble la meilleure.
certains / sous-paquet / Util.groovy
@GrabResolver(name = 'nexus', root = 'https://local-nexus-server:8443/repository/maven-public', m2Compatible = true) @Grab('com.google.errorprone:error_prone_annotations:2.1.3') @Grab('com.google.guava:guava:23.0') @GrabExclude('com.google.errorprone:error_prone_annotations') import com.google.common.base.Ssortingngs class Util { void msg(int a, Ssortingng b, Map c) { println 'Message printed by msg method inside Util.groovy' println "Print 5 asterisks using the Guava dependency ${Ssortingngs.repeat("*", 5)}" println "Arguments are a=$a, b=$b, c=$c" } }
example.groovy
#!/usr/bin/env groovy Class clazz = new GroovyClassLoader().parseClass("${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy" as File) GroovyObject u = clazz.newInstance() u.msg(1, 'b', [a: 'b', c: 'd'])
Pour exécuter le script example.groovy
, ajoutez-le à votre chemin système et tapez depuis n’importe quel répertoire:
example.groovy
Le script imprime:
Message printed by msg method inside Util.groovy Print 5 asterisks using the Guava dependency ***** Arguments are a=1, b=b, c=[a:b, c:d]
L’exemple ci-dessus a été testé dans l’environnement suivant: Groovy Version: 2.4.13 JVM: 1.8.0_151 Vendor: Oracle Corporation OS: Linux
L’exemple montre ce qui suit:
Util
dans un script groovy. Util
qui appelle la bibliothèque tierce Guava
en l’incluant comme une dépendance Grape
( @Grab('com.google.guava:guava:23.0')
). Util
peut résider dans un sous-répertoire. Util
. Commentaires / suggestions supplémentaires:
new Util()
, mais surtout, elle devrait être placée dans un fichier nommé à part Util.groovy. Reportez-vous à Scripts et classes pour plus de détails sur les différences entre les scripts groovy et les classes groovy. "${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy"
au lieu de "some/subpackage/Util.groovy"
. Cela garantira que le fichier Util.groovy
sera toujours trouvé par rapport à l’emplacement du script groovy ( example.groovy
) et non au répertoire de travail actuel. Par exemple, utiliser "some/subpackage/Util.groovy"
entraînerait une recherche dans WORK_DIR/some/subpackage/Util.groovy
. myScript.groovy
est un nom de script et MyClass.groovy
est un nom de classe. Nommer my-script.groovy
entraînera des erreurs d’exécution dans certains scénarios car la classe résultante n’aura pas de nom de classe Java valide.