जिसमें एक अन्य ग्रूवी में एक ग्रूवी स्क्रिप्ट शामिल है


97

मैंने पढ़ा है कि कैसे एक ग्रूवी फ़ाइल को किसी अन्य ग्रूवी स्क्रिप्ट में आयात करना है

मैं एक ग्रूवी फ़ाइल में सामान्य कार्यों को परिभाषित करना चाहता हूं और अन्य ग्रूवी फ़ाइलों से उन कार्यों को कॉल करना चाहता हूं।

मैं समझता हूं कि यह ग्रूवी का उपयोग स्क्रिप्टिंग भाषा की तरह होगा, अर्थात मुझे कक्षाओं / वस्तुओं की आवश्यकता नहीं है। मैं dsl की तरह कुछ करने की कोशिश कर रहा हूं जिसे ग्रूवी में किया जा सकता है। सभी चर जावा से मुखर होंगे और मैं एक शेल में ग्रूवी स्क्रिप्ट निष्पादित करना चाहता हूं।

क्या यह वास्तव में संभव है ? क्या कोई उदाहरण दे सकता है।


जवाबों:


107
evaluate(new File("../tools/Tools.groovy"))

इसे अपनी स्क्रिप्ट के शीर्ष पर रखें। यह एक ग्रूवी फ़ाइल की सामग्री में लाएगा (बस फ़ाइल के नाम को आपके ग्रूवी स्क्रिप्ट के साथ दोहरे उद्धरणों के बीच बदलें)।

मैं आश्चर्यजनक रूप से "Tools.groovy" नामक एक वर्ग के साथ ऐसा करता हूं।


7
इस कार्य के लिए फ़ाइल नाम को जावा के वर्ग के नामकरण नियमों के अनुरूप होना चाहिए।
विस्किल

2
प्रश्न - मैं इस वाक्य-विन्यास का उपयोग करके जिस स्क्रिप्ट का मूल्यांकन कर रहा हूँ, उसके लिए मैं तर्क कैसे पास कर सकता हूँ?
स्टीव

3
@steve आप नहीं कर सकते हैं, लेकिन आप उस स्क्रिप्ट में एक फ़ंक्शन को परिभाषित कर सकते हैं जिसे आप तर्कों के साथ कहते हैं
Nilzor

11
यह काम नहीं करता है ... स्क्रिप्ट का मूल्यांकन अच्छी तरह से किया जाता है, लेकिन कॉलर स्कोप (
डिफ

3
आपको एक कॉल से एक ऑब्जेक्ट वापस करना होगा, फिर एक चर के लिए मूल्यांकन परिणाम असाइन करें।
लोगनमज़

45

ग्रूवी 2.2 के रूप में नए @BaseScriptएएसटी ट्रांसफॉर्म एनोटेशन के साथ बेस स्क्रिप्ट क्लास घोषित करना संभव है ।

उदाहरण:

फ़ाइल MainScript.groovy :

abstract class MainScript extends Script {
    def meaningOfLife = 42
}

फ़ाइल परीक्षण। groovy :

import groovy.transform.BaseScript
@BaseScript MainScript mainScript

println "$meaningOfLife" //works as expected

1
मैं इस पद्धति का उपयोग करते समय "वर्ग को हल करने में असमर्थ" प्राप्त करता रहता हूं। आम मेरे करने के लिए क्या सिफारिश करेंगे? क्या कस्टम क्लासेस को किसी अन्य ग्रूवी स्क्रिप्ट में आयात करने का कोई तरीका है?
droidnoob

38

ऐसा करने का एक और तरीका है कि एक ग्रूवी क्लास और पार्स में फंक्शन्स को परिभाषित करना और रन-वे पर क्लासपाथ में फाइल जोड़ना:

File sourceFile = new File("path_to_file.groovy");
Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile);
GroovyObject myObject = (GroovyObject) groovyClass.newInstance();

3
इस समाधान ने वास्तव में मेरे लिए सबसे अच्छा काम किया। जब मैंने स्वीकार किए गए उत्तर का उपयोग करने की कोशिश की, तो मुझे यह कहते हुए एक त्रुटि हुई कि मेरी मुख्य ग्रूवी स्क्रिप्ट मूल्यांकन की गई स्क्रिप्ट में परिभाषित वर्ग को हल करने में असमर्थ थी। इसके लायक क्या है ...
cBlaine

1
मैंने एसओ पर पोस्ट किए गए कई अलग-अलग तरीकों की कोशिश की और केवल यह काम किया। दूसरों ने कक्षा या विधियों को हल करने में सक्षम नहीं होने के बारे में त्रुटियों को फेंक दिया। यह वह संस्करण है जिसका मैं संस्करण Groovy संस्करण का उपयोग कर रहा हूं: 2.2.2 JVM: 1.8.0 विक्रेता: Oracle Corporation OS: Windows 7.
Kuberchaun

1
इसने बहुत अच्छा काम किया। GroovyObjectस्पष्ट रूप से उपयोग करना सुनिश्चित करें , यह आपके अपने वर्ग के नाम के लिए प्लेसहोल्डर नहीं है।
haventchecked

1
फिर भी मुझे मिलता है: java.lang.NoClassDefFoundError: groovy.lang.GroovyObject
dokaspar

जीवन रक्षक। धन्यवाद मेरे साथी!!
अंजना सिल्वा

30

मुझे लगता है कि सबसे अच्छी पसंद ग्रूवी कक्षाओं के रूप में उपयोगिता चीजों को व्यवस्थित करना है, उन्हें क्लासपाथ में जोड़ें और मुख्य स्क्रिप्ट को आयात कीवर्ड के माध्यम से संदर्भित करने दें।

उदाहरण:

लिपियों / DbUtils.groovy

class DbUtils{
    def save(something){...}
}

लिपियों / script1.groovy:

import DbUtils
def dbUtils = new DbUtils()
def something = 'foobar'
dbUtils.save(something)

रनिंग स्क्रिप्ट:

cd scripts
groovy -cp . script1.groovy

मुझे आश्चर्य है कि यह कैसे काम करेगा यदि आपके पास एक निर्देशिका संरचना है जैसे libऔर srcनिर्देशिका
Gi0rgi0s

9

जिस तरह से मैं ऐसा करता हूं वह है GroovyShell

GroovyShell shell = new GroovyShell()
def Util = shell.parse(new File('Util.groovy'))
def data = Util.fetchData()

7

ग्रूवी के पास विशिष्ट स्क्रिप्टिंग भाषाओं की तरह एक आयात कीवर्ड नहीं है जो एक अन्य फ़ाइल की सामग्री को शाब्दिक रूप से शामिल करेगा (यहां दिया गया है: क्या ग्रूवी में एक शामिल तंत्र प्रदान करता है? )।
इसके ऑब्जेक्ट / क्लास ओरिएंटेड प्रकृति के कारण, आपको इस काम जैसी चीजें बनाने के लिए "गेम खेलना" पड़ता है। एक संभावना आपके सभी उपयोगिता कार्यों को स्थिर बनाने की है (क्योंकि आपने कहा था कि वे वस्तुओं का उपयोग नहीं करते हैं) और फिर अपने निष्पादन शेल के संदर्भ में एक स्थिर आयात करते हैं। फिर आप इन तरीकों को "वैश्विक फ़ंक्शन" कह सकते हैं।
एक अन्य संभावना एक बाध्यकारी वस्तु का उपयोग करना होगा ( http://groovy.codehaus.org/api/groovy/lang/Binding.html) अपना शेल बनाते समय और उन सभी फ़ंक्शंस को बाध्य करने के लिए जिन्हें आप विधियों के लिए चाहते हैं (यहाँ नकारात्मक पक्ष बंधन में सभी विधियों को शामिल करना होगा लेकिन आप शायद प्रतिबिंब का उपयोग कर सकते हैं)। फिर भी एक अन्य उपाय यह होगा methodMissing(...)कि आप अपने शेल को सौंपे गए प्रतिनिधि ऑब्जेक्ट में ओवरराइड करें जो आपको मूल रूप से एक मैप का उपयोग करके डायनामिक डिस्पैच करने की अनुमति देता है या जो भी विधि आपको पसंद आएगी ।

इनमें से कई तरीकों का प्रदर्शन यहां किया गया है: http://www.nextinstruction.com/blog/2012/01/08/creating-dsls-with-groovy/ । अगर आप किसी विशेष तकनीक का उदाहरण देखना चाहते हैं तो मुझे बताएं।


7
यह लिंक अब मृत हो गया है
निकोलस मम्मैर्ट्स

7

बाहरी स्क्रिप्ट को जावा वर्ग के रूप में कैसे मानें? इस लेख के आधार पर: https://www.jmdawson.net/blog/2014/08/18/use-functions-from-one-groovy-script-in-another/

getThing.groovy बाहरी स्क्रिप्ट

def getThingList() {
    return ["thing","thin2","thing3"]
}

PrintThing.groovy मुख्य स्क्रिप्ट

thing = new getThing()  // new the class which represents the external script
println thing.getThingList()

परिणाम

$ groovy printThing.groovy
[thing, thin2, thing3]

6

यहां एक स्क्रिप्ट को दूसरे के भीतर शामिल करने का एक पूरा उदाहरण है।
बस Testmain.groovy फ़ाइल को चलाएं
व्याख्यात्मक टिप्पणियां शामिल हैं क्योंकि मैं उस तरह अच्छा हूं;]

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

0

देर से आने वालों के लिए, ऐसा प्रतीत होता है कि ग्रूवी अब उस :load file-pathकमांड का समर्थन करता है जो दिए गए फ़ाइल से इनपुट को पुनर्निर्देशित करता है, इसलिए लाइब्रेरी लाइब्रेरी को शामिल करना अब तुच्छ हो गया है।

यह एक लोड की गई फ़ाइल में groovysh और एक लाइन के इनपुट के रूप में काम करता है:
groovy:000> :load file1.groovy

file1.groovy में हो सकता है:
:load path/to/another/file invoke_fn_from_file();


क्या आप कृपया इस पर विस्तार कर सकते हैं? डॉक्स में यह कहां है? मैं कहाँ रखूँ :load file-path?
क्रिस्टोफर हैमरस्ट्रॉम

अच्छी तरह से, यह एक लोड की गई फ़ाइल में groovysh और एक लाइन के रूप में इनपुट के रूप में काम करता है: <br/> groovy:000> :load file1.groovy file1.groovy में ये शामिल हो सकता है: <br/>:load path/to/another/file
जैक पंट

1
मुझे डॉक्स में लोड मिला । अगर मैं सही ढंग से समझूं , तो यह केवल ग्रूवीश के साथ काम करता है?
क्रिस्टोफ़र हैमरस्ट्रॉम

यह एक चर के अंदर परिभाषित पथ के साथ काम नहीं करेगा, हालांकि, यह होगा?
user2173353

0

कुछ बदलावों के साथ @grahamparks और @snowindy के जवाबों का एक संयोजन है, जो टॉमकैट पर चलने वाली मेरी ग्रूवी स्क्रिप्ट के लिए काम करता है:

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 compile time errors!!
foo.doSth(); // Actually works!

मुझे मिलता है: java.lang.NoClassDefFoundError: groovy.lang.GroovyObject
dokaspar

0

ग्रूवी अन्य ग्रूवी कक्षाओं को आयात कर सकता है जैसे जावा करता है। बस सुनिश्चित करें कि लाइब्रेरी फ़ाइल का विस्तार .groovy है।

    $ cat lib/Lib.groovy
    package lib
    class Lib {
       static saySomething() { println 'something' }
       def sum(a,b) { a+b }
    }

    $ cat app.gvy
    import lib.Lib
    Lib.saySomething();
    println new Lib().sum(37,5)

    $ groovy app
    something
    42

-1

कुछ जांच के बाद मैं इस निष्कर्ष पर पहुंचा हूं कि निम्नलिखित दृष्टिकोण सबसे अच्छा लगता है।

कुछ / सबपैकेज / 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.Strings

class Util {
    void msg(int a, String b, Map c) {
        println 'Message printed by msg method inside Util.groovy'
        println "Print 5 asterisks using the Guava dependency ${Strings.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'])

example.groovyस्क्रिप्ट को चलाने के लिए , इसे अपने सिस्टम पथ में जोड़ें और किसी भी निर्देशिका से टाइप करें:

example.groovy

स्क्रिप्ट प्रिंट:

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]

उपरोक्त उदाहरण निम्नलिखित पर्यावरण में परीक्षण किया गया था: Groovy Version: 2.4.13 JVM: 1.8.0_151 Vendor: Oracle Corporation OS: Linux

उदाहरण निम्नलिखित प्रदर्शित करता है:

  • Utilएक ग्रूवी स्क्रिप्ट के अंदर एक वर्ग का उपयोग कैसे करें ।
  • एक Utilवर्ग Guavaइसे Grapeनिर्भरता ( @Grab('com.google.guava:guava:23.0')) के रूप में शामिल करके तीसरे पक्ष के पुस्तकालय को बुलाता है ।
  • Utilवर्ग एक उपनिर्देशिका में निवास कर सकते हैं।
  • Utilकक्षा के भीतर एक विधि के लिए तर्क पारित करना ।

अतिरिक्त टिप्पणियाँ / सुझाव:

  • हमेशा अपने ग्रूवी स्क्रिप्ट के भीतर पुन: प्रयोज्य कार्यक्षमता के लिए ग्रूवी स्क्रिप्ट के बजाय एक ग्रूवी क्लास का उपयोग करें। उपरोक्त उदाहरण Util.groovy फ़ाइल में परिभाषित Util वर्ग का उपयोग करता है। पुन: प्रयोज्य कार्यक्षमता के लिए ग्रूवी लिपियों का उपयोग करना समस्याग्रस्त है। उदाहरण के लिए, यदि एक ग्रूवी लिपि का उपयोग किया जाता है, तो लिटील वर्ग को स्क्रिप्ट के निचले भाग में तत्काल new Util()भेजना होगा, लेकिन सबसे महत्वपूर्ण बात यह है कि इसे Util.groovy नाम की किसी भी फ़ाइल में रखा जाएगा। ग्रूवी स्क्रिप्ट और ग्रूवी कक्षाओं के बीच अंतर के बारे में अधिक जानकारी के लिए लिपियों बनाम कक्षाओं का संदर्भ लें ।
  • उपरोक्त उदाहरण में मैं "${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy"इसके बजाय पथ का उपयोग करता हूं "some/subpackage/Util.groovy"। यह गारंटी देगा कि Util.groovyफ़ाइल हमेशा ग्रूवी स्क्रिप्ट के स्थान ( example.groovy) के संबंध में मिलेगी न कि वर्तमान कार्यशील निर्देशिका के लिए। उदाहरण के लिए, उपयोग "some/subpackage/Util.groovy"करने के परिणामस्वरूप खोजा जाएगा WORK_DIR/some/subpackage/Util.groovy
  • अपनी ग्रूवी लिपियों के नाम के लिए जावा वर्ग के नामकरण सम्मेलन का पालन करें। मैं व्यक्तिगत रूप से एक छोटे से विचलन को पसंद करता हूं जहां स्क्रिप्ट एक पूंजी के बजाय एक कम पत्र के साथ शुरू होती हैं। उदाहरण के लिए, myScript.groovyएक स्क्रिप्ट नाम है, और MyClass.groovyएक वर्ग नाम है। नामकरण my-script.groovyमें कुछ परिदृश्यों में रनटाइम त्रुटियों का परिणाम होगा क्योंकि परिणामी वर्ग में एक वैध जावा वर्ग नाम नहीं होगा।
  • सामान्य रूप से JVM की दुनिया में प्रासंगिक कार्यक्षमता का नाम JSR 223: जावा के लिए स्क्रिप्टिंग है । विशेष रूप से ग्रूवी में कार्यक्षमता का नाम ग्रूवी एकीकरण तंत्र है । वास्तव में, इसी दृष्टिकोण का उपयोग ग्रूवी या जावा के भीतर से किसी भी जेवीएम भाषा को कॉल करने के लिए किया जा सकता है । ऐसी जेवीएम भाषाओं के कुछ उल्लेखनीय उदाहरण ग्रूवी, जावा, स्काला, जेरी, और जावास्क्रिप्ट (राइनो) हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.