Table of Contentsgenerated with DocToc
一、使用场景二、市面上表达式引擎比较 2.1 Aviator2.2 Jexl
一、使用场景
在做某些项目的时候,有时会遇到如下情景:
用户需要传入某个JAVA 表达式,然后后台将这个表达式当作JAVA代码执行
二、市面上表达式引擎比较
我们有许多表达式引擎可供选择:
JexlAviator
2.1 Aviator
avitor具体使用技巧可以参考这篇博客:/keda8997110/article/details/50782848
avitor可以满足基本的表达式的判断,但对于对象中的函数调用明显力不从心,如果碰到以下业务情景:
用户传入的java表达式是:user.getName().equals(“123456”);
这个表达式是调用user对象里的getName方法,然后再掉用equals方法,判断是否等于字符串123456,avitor对于调用对象的方法这个问题也有自己的解决方法:
User user = new User("123456");//首先要注入User的类AviatorEvaluator.addInstanceFunctions("user", User.class);//再使用aviator特定的表达式运行方法: namespace.method(instance, args)AviatorEvaluator.execute("User.getName(user)=='123456'")
这样太麻烦了,虽然程序可以事先将需要的类注入到AviatorEvaluator引擎中,但是我们还需要将熟悉的java表达式转化为Aviator需要的表达式形式。
那我们有没有可以直接执行java代码的呢?有!
2.2 Jexl
我们在maven中使用Jexl需要导入如下依赖:
<!-- /artifact/mons/commons-jexl --><dependency><groupId>mons</groupId><artifactId>commons-jexl</artifactId><version>2.1.1</version></dependency>
然后看我们的 Jexl 如何实现业务:
首先我们实现一个方法,用于动态加载函数用户传入的java表达式是:user.getName().equals(“123456”);
然后后台直接执行
//动态加载方法//jexlExp -- java表达式//map -- 运行环境private Object invokeMethod(String jexlExp, Map<String,Object> map){JexlEngine jexl=new JexlEngine();Expression e = jexl.createExpression(jexlExp);JexlContext jc = new MapContext();for(String key:map.keySet()){jc.set(key, map.get(key));}if(null==e.evaluate(jc)){return "";}return e.evaluate(jc);}
然后编写测试用例:
pubic class User{String name = "123456";public User(String name){this.name = name;}public String getName(){return name;}}
public class JexlTest {private Map<String, Object> env;//注入测试环境,将变量形成一个map<对象名,对象>@Beforepublic void before(){env = new HashMap<>();env.put("id","123456");env.put("user",new User());}//动态加载方法private Object invokeMethod(String jexlExp, Map<String,Object> map){JexlEngine jexl=new JexlEngine();Expression e = jexl.createExpression(jexlExp);JexlContext jc = new MapContext();for(String key:map.keySet()){jc.set(key, map.get(key));}if(null==e.evaluate(jc)){return "";}return e.evaluate(jc);}//调用Jexl执行引擎@Testpublic void TestFunctionMethod(){String expression="user.getId().equals(id)";boolean res = (boolean) invokeMethod(expression,env);Assert.assertTrue(res);}}
执行结果为true
与Aviator相比,我们省去了修改表达式的步骤
如果觉得《Jexl表达式引擎-根据字符串动态执行JAVA》对你有帮助,请点赞、收藏,并留下你的观点哦!