Java中使用Groovy实现自定义表达式解析

me87re 9年前


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

</div>