在應用中,我們可以在一個Java類、一個Groovy類或者一個Groovy腳本中實現某個特定功能。之后可以在Java類、Groovy類或Groovy腳本中調用該功能。
在groovy 使用groovy類,無需做什么,直接就可以工作。我們只需要確保所依賴的類在在類路徑下,要么是源碼,要么是字節碼。
要再groovy類中執行groovy腳本,我們可以使用,groovyShell。
要在java類中使用groovy腳本,則可以使用ScriptEngine API。
如想在java中使用groovy類,或者在groovy類中使用java類,則可以使用groovy聯合編譯工具
開發環境搭建
- 使用maven管理項目
- 依賴最新版本groovy ,groovy-all
- 確保你的ide下載了groovy插件。本次使用idea開發
使用ide自動編譯,可以幫我們省去很多手動編譯的麻煩
groovy 中使用groovy類
在Groovy代碼中使用一個groovy類,只需要確保該類在我們的classpath下。當我們在groovy代碼中引用一個groovy類時,Groovy會以該類的名字,在我們的classpath下查找.groovy文件,如果找不到則以相同的名字查找.class文件
code
package com.xxx.groovy.service import groovy.transform.TypeChecked import groovy.transform.TypeCheckingMode class GroovySerice { @TypeChecked def shoutString(String str) { println "Printing in uppercase" println str.toUpperCase() println "Printing again in uppercase" println str.toUpperCase() } @TypeChecked def printInReverse(String str) { println str.reverse() } @TypeChecked(TypeCheckingMode.SKIP) def use(Object instance) { if (instance instanceof String) { println instance.length() } else { println instance } } def pickEven(n, b, block) {//傳遞閉包 println b for (int i = 0; i <= n; i += 2) { block(i) } } }
在另一個groovy類中調用groovy
package com.xxx.groovy.service class RunGroovy { private GroovySerice groovySerice = new GroovySerice() public static void main(String[] args) { new RunGroovy().groovySerice.shoutString("hello world") } }
利用聯合編譯使用混合使用Groovy和java
如果Groovy類是預先編譯好的,那我們就可以方便地在Java中使用.class文件或JAR包。來自Java的字節碼和來自Groovy的字節碼,對Java而言沒什么區別.
如果我們只有Groovy源代碼,而非字節碼,又會怎樣呢?請記住,當我們的Java類依賴其他Java類時,如果沒有找到字節碼,javac將編譯它認為必要的任何Java類。不過javac對Groovy可沒這么友好。幸好groovyc支持聯合編譯.當我們編譯Groovy代碼時,它會確定是否有任何需要編譯的Java類,並負責編譯它們
public class AJavaClass { { System.out.println("Created Java Class"); } public void sayHello() { System.out.println("hello"); } }
//groovy new AJavaClass().sayHello()
要聯合編譯這兩個文件,我們輸入這個命令:groovyc -j AJavaClass.java
UseJavaClass.groovy -Jsource 1.6。-Jsource 1.6會把可選的選項source = 1.6發送給Java編譯器。使用javap檢查生成的字節碼,會發現AJavaClass作為一個普通的Java類
執行以下代碼
java -classpath $GROOVY_HOME/embeddable/groovy-all-2.1.0.jar:. UseJavaClass
輸入如下:
Created Java Class hello
當然我們使用ide執行執行即可
在Java中調用Groovy動態方法
每個Groovy對象都實現了GroovyObject接口,該接口有一個叫作invokeMethod()的特殊方法。該方法接受要調用的方法的名字,以及要傳遞的參數。在Java這一端,invokeMethod()可以用來調用Groovy中使用元編程
創建一個Groovy類,其中包含一個特殊方法——methodMissing(),當某個不存在的方法被調用時,該方法會介入
class DynamicGroovyClass { def methodMissing(String name, args) { println "You called $name with ${args.join(', ')}." args.size() } }
要從Java端調用我們期望的方法,可調用invokeMethod(),並將方法的名字和一個由參數組成的數組傳給它
public class CallDynamicMethod { public static void main(String[] args) { groovy.lang.GroovyObject instance = new DynamicGroovyClass(); Object result1 = instance.invokeMethod("squeak", new Object[] {}); System.out.println("Received: " + result1); Object result2 = instance.invokeMethod("quack", new Object[] {"like", "a", "duck"}); System.out.println("Received: " + result2); } }
輸出結果如下:
You called squeak with .
Received: 0
You called quack with like, a, duck.
Received: 3
當然我們亦可以把groovy腳本當成一個字符串傳入:
//groovy 代碼 package com.xxx.logclean.services import com.google.common.collect.Lists import org.slf4j.Logger import org.slf4j.LoggerFactory /** * Created by hao.su on 15/11/23. */ public class GroovyServiceImpl implements IGroovyService { private Logger logger = LoggerFactory.getLogger(GroovyServiceImpl.class); @Override Object execute(String groovyScript, Map params) { Class<GroovyObject> groovyObjectClass = parseScript(groovyScript) GroovyObject groovyObject try { groovyObject = groovyObjectClass.newInstance() } catch (any) { logger.error("error when execute groovyScript:{}", any) throw new RuntimeException("error,when execute groovyScript", any) } ArrayList<String> list = Lists.newArrayList(); return groovyObject.invokeMethod("validate", [params, list] as Object[]) } private Class<GroovyObject> parseScript(String script) { GroovyClassLoader loader = new GroovyClassLoader(); Class<GroovyObject> clazz = loader.parseClass(script) clazz } }
java 代碼
public static void main(String[] args) { Map<String, Object> map = Maps.newHashMap(); map.put("a", 1); map.put("b", 2); map.put("c", 3); map.put("d", 4); List<String> list = Lists.newArrayList(new String[]{"a", "b", "c"}); map.put("d", 5); map.put("keys",list); String groovyScript = "import java.util.regex.Matcher\n" + "import java.util.regex.Pattern\n" + "def validate(Map dataMap,List list) {\n" + " def returnList = []\n" + " List<String> keys = dataMap.get(\"keys\")\n" + " for (key in keys) {\n" + " if (dataMap.containsKey(key)) {\n" + " String value = dataMap.get(key);\n" + " if (key == \"userId\") {\n" + " Pattern pattern = Pattern.compile(\"[0-9]*\")\n" + " Matcher isNum = pattern.matcher(value);\n" + " if (!isNum.matches()) {//過濾臟數據\n" + " return []\n" + " }\n" + " }\n" + " returnList.add(value)\n" + " }\n" + " }\n" + " returnList\n" + "}"; IGroovyService impl = new GroovyServiceImpl(); List<String> returnList = (List<String>) impl.execute(groovyScript, map); for(String str:returnList){ System.out.println(str); } }
輸出結果如下:
1
2
3
groovy中使用java
在Groovy中使用Java類簡單且直接。如果我們想使用的Java類是JDK的一部分,可以像在Java中那樣導入這些類或它們的包
如果想使用一個自己的Java類,或者不是標准JDK中的類,在Groovy中可以像在Java中那樣導入它們。請確保導入了必要的包或類,或者使用類的全限定名來引用它們
public class GreetJava { public static void sayHello() { System.out.println("Hello Java"); } }
UseGreetJava.groovy
//groovy com.agiledeveloper.GreetJava.sayHello()
我們想從一個Groovy腳本中調用該方法,因此首先編譯Java類GreetJava.
要運行該腳本,只需要輸入groovy UseGreetJava。該腳本會順利運行,並調用GreetJava類中的sayHello()方法
Hello Java