Java中使用Groovy實現自定義表達式解析
Groovy作為一種JVM-Based語言,目前普及程度正在提高。本文演示一下在Java類中,通過繼承GDK的groovy.lang.Script類如何支持自定義表達式解析功能。
輸入:
表示一行數據的某個map結構。在實際應用中,產生這種結構的最常見場景可能是通過JDBC訪問數據庫、通過調用WebService服務得到的某行結果集等。
目標設定:
假設我們希望對輸入數據進行某個運算。此處示例中,我們模擬oracle中最常用的nvl函數。
處理過程:
首先,通過繼承groovy.lang.Script,定義自己的表達式解析類:
public class MyBasicScript extends Script
在該類中實現具體的解析方法:
public static Object nvl(Object str,Object val){ return str==null ||"".equals(str)?val:str; }
其次,基于上述自定義類,實例化一個CompilerConfiguration對象。
CompilerConfiguration cfg = new CompilerConfiguration(); cfg.setScriptBaseClass(MyBasicScript.class.getName());
以此CompilerConfiguration實例為參數,實例化一個GroovyShell對象
shell = new GroovyShell(cfg);
通過shell對象,解析并運行表達式。在運行前,可以通過bingding對象綁定腳本運行時的上下文數據:
Binding binding = new Binding(map); Script script = shell.parse(expr); script.setBinding(binding); script.run();
附完整的代碼示例(共兩個類,分別是自定義腳本實現類、調用及測試類)
package jg.groovy; import groovy.lang.Script; import java.lang.reflect.Method; public class MyBasicScript extends Script { @Override public Object run() { //show usage Method[] methods = MyBasicScript.class.getDeclaredMethods(); StringBuilder sb=new StringBuilder(); for (Method method : methods) { sb.append(method); } return sb.substring(0, sb.length()-1); } public static Object nvl(Object str, Object val) { return str == null || "".equals(str) ? val : str; } }
package jg.groovy; import groovy.lang.Binding; import groovy.lang.GroovyShell; import groovy.lang.Script; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import org.codehaus.groovy.control.CompilerConfiguration; public class ExprSupport { private static final Object lock = new Object(); private static final GroovyShell shell; private static Hashtable<String, Script> cache = new Hashtable<String, Script>(); static { CompilerConfiguration cfg = new CompilerConfiguration(); cfg.setScriptBaseClass(MyBasicScript.class.getName()); shell = new GroovyShell(cfg); } public static Object parseExpr(String expr) { Script s = getScriptFromCache(expr); return s.run(); } public static Object parseExpr(String expr, Map<?, ?> map) { Binding binding = new Binding(map); Script script = getScriptFromCache(expr); script.setBinding(binding); return script.run(); } private static Script getScriptFromCache(String expr) { if (cache.contains(expr)) { return cache.get(expr); } synchronized (lock) { if (cache.contains(expr)) { return cache.get(expr); } Script script = shell.parse(expr); cache.put(expr, script); return script; } } /** * @param args */ public static void main(String[] args) { // eg. get one row from db Map<String, Object> row = new HashMap<String, Object>(); row.put("id", 42); row.put("name", ""); //帶綁定數據參數的調用方式 System.out.println(ExprSupport.parseExpr("nvl(id,0)", row)); System.out.println(ExprSupport.parseExpr("nvl(name,'anonymous')", row)); //不帶綁定數據參數的調用方式,這個是groovy的內置能力 System.out.println(ExprSupport.parseExpr("1+2")); } }
輸出:
42 anonymous 3
總結:結合groovy對表達式的內置支持能力與自定義腳本能力,可以實現功能強大的表達式解析能力。
來自:http://www.cnblogs.com/ora11g/p/4473544.html
本文由用戶 me87re 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!