Groovy小結:java調用Groovy方法並傳遞參數
@(JAVA總結)
1. 場景描述
在網上查了資料發現,java有三種方式調用groovy腳本。但是真正在實際的服務器環境中,嵌入groovy腳本往往需要滿足下面的條件:
- 可以直接調用groovy腳本中的方法
- 能傳遞對象到groovy方法中,不僅僅是字符串
- 提供腳本緩存機制,不用每次調用腳本的時候,都到磁盤讀取
- 修改groovy后能實時生效
只有滿足了上面的這些要求,才能安心的將其嵌入到現有的Java后台服務中。
下面就來具體探討下具體實現的步驟。
2. 解決方案
其實,GroovyScriptEngine類就已經提供了上面所說的功能。
主要使用GroovyScriptEngine.loadScriptByName來讀取腳本,loadScriptByName方法內部提供了緩存功能,在讀取groovy腳本的時候,會優先從緩存中讀取,如果緩存中沒有的話,才去讀取腳本,如下:
2.1 相關測試類和腳本
在后面的測試后,會用到下面的java類和groovy腳本。
2.1.1 測試類Person.java
該類用於測試傳遞Java對象到Groovy腳本中
public class Person {
public String name;
public String address;
public Integer age;
public Person(String name, String addr, Integer age){
this.name = name;
this.address = addr;
this.age = age;
}
public String toString(){
return String.format("[Person: name:%s, address:%s, age:%s]", name,address, age);
}
}
2.1.2 測試腳本hello2.groovy
下面腳本中的兩個方法用於測試方法的無參調用和帶參調用
def helloWithoutParam(){
println "start to call helloWithoutParam!"
return "success, helloWithoutParam";
}
def helloWithParam(person, id){
println "start to call helloWithParam, param{person:" + person + ", id:" + id + "}";
return "success, helloWithParam";
}
2.2 java調用Groovy腳本方法(無參)
public static void testGroovy2(){
try {
Class scriptClass = groovyScriptEngine.loadScriptByName("hello2.groovy");
GroovyObject scriptInstance = (GroovyObject)scriptClass.newInstance();
Object ret = scriptInstance.invokeMethod("helloWithoutParam", null);
System.out.println("testGroovy2:" + ret);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception e="+e.toString());
}
}
執行結果:
start to call helloWithoutParam!
testGroovy2: success, helloWithoutParam
2.3 java調用Groovy腳本方法(帶參)
@SuppressWarnings({ "rawtypes" })
public static void testGroovy3(){
try {
Person person = new Person("wchi", "nanjing", 30);
Class scriptClass = groovyScriptEngine.loadScriptByName("hello2.groovy");
GroovyObject scriptInstance = (GroovyObject)scriptClass.newInstance();
Object ret = scriptInstance.invokeMethod("helloWithParam", new Object[]{person,"lxi"});
System.out.println("testGroovy3:" + ret);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception e="+e.toString());
}
}
返回結果:
start to call helloWithParam, param{person:[Person: name:wchi, address:nanjing, age:30], id:lxi}
testGroovy3: success, helloWithParam
2.4 封裝的公用類
可以將上面的代碼封裝成公用類,這樣就方便很多,如下:
public class GroovyCommonUtil {
private static final Logger log = LoggerFactory.getLogger(GroovyCommonUtil.class);
//該變量用於指明groovy腳本所在的父目錄
static String root[]=new String[]{"bin/groovy/"};
static GroovyScriptEngine groovyScriptEngine;
static{
try {
groovyScriptEngine=new GroovyScriptEngine(root);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 用於調用指定Groovy腳本中的指定方法
* @param scriptName 腳本名稱
* @param methodName 方法名稱
* @param params 方法參數
* @return
*/
@SuppressWarnings({ "rawtypes"})
public Object invokeMethod(String scriptName, String methodName, Object... params) throws Exception{
Object ret = null;
Class scriptClass = null;
GroovyObject scriptInstance = null;
try {
scriptClass = groovyScriptEngine.loadScriptByName(scriptName);
scriptInstance = (GroovyObject)scriptClass.newInstance();
} catch (ResourceException | ScriptException | InstantiationException | IllegalAccessException e1) {
log.warn("加載腳本["+scriptName+"]出現異常", e1);
throw new Exception("加載腳本"+scriptName+"失敗");
}
try {
ret = (String)scriptInstance.invokeMethod(methodName, params);
} catch (IllegalArgumentException e) {
log.warn("執行方法" + methodName + "參數出現異常, 參數為" + params, e);
throw new Exception("調用方法[" + methodName + "]失敗,因參數不合法");
} catch(Exception e){
log.warn("執行方法" + methodName + "出現異常", e);
throw new Exception("調用方法[" + methodName + "]失敗");
}
return ret;
}
使用上面的公用類,改寫的測試代碼如下:
/**
* 測試沒有參數的方法調用
*/
public static void testGroovyWithoutParam(){
String result = (String)GroovyCommonUtil.invokeMethod("hello2.groovy", "helloWithoutParam");
System.out.println("testGroovy4: " + result + "\n");
}
/**
* 測試攜帶參數的方法調用
*/
public static void testGroovyWithParam(){
Person person = new Person("wchi", "nanjing", 30);
String result = (String)GroovyCommonUtil.invokeMethod("hello2.groovy", "helloWithParam", person, "testGroovy4");
System.out.println("testGroovy4: " + result + "\n");
}