Groovy小結:java調用Groovy方法並傳遞參數


Groovy小結:java調用Groovy方法並傳遞參數

@(JAVA總結)

1. 場景描述

在網上查了資料發現,java有三種方式調用groovy腳本。但是真正在實際的服務器環境中,嵌入groovy腳本往往需要滿足下面的條件:

  1. 可以直接調用groovy腳本中的方法
  2. 能傳遞對象到groovy方法中,不僅僅是字符串
  3. 提供腳本緩存機制,不用每次調用腳本的時候,都到磁盤讀取
  4. 修改groovy后能實時生效

只有滿足了上面的這些要求,才能安心的將其嵌入到現有的Java后台服務中。
下面就來具體探討下具體實現的步驟。

2. 解決方案

其實,GroovyScriptEngine類就已經提供了上面所說的功能。
主要使用GroovyScriptEngine.loadScriptByName來讀取腳本,loadScriptByName方法內部提供了緩存功能,在讀取groovy腳本的時候,會優先從緩存中讀取,如果緩存中沒有的話,才去讀取腳本,如下:
Alt text

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");
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM