• Jexl表达式引擎-根据字符串动态执行JAVA


    Table of Contents generated with DocToc

    一、使用场景

    在做某些项目的时候,有时会遇到如下情景:

    用户需要传入某个JAVA 表达式,然后后台将这个表达式当作JAVA代码执行


    二、市面上表达式引擎比较

    我们有许多表达式引擎可供选择:

    • Jexl
    • Aviator

    2.1 Aviator

    avitor具体使用技巧可以参考这篇博客:https://blog.csdn.net/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 需要导入如下依赖:

    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-jexl -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-jexl</artifactId>
      <version>2.1.1</version>
    </dependency>
    

    然后看我们的 Jexl 如何实现业务:

    用户传入的java表达式是:user.getName().equals(“123456”);
    然后后台直接执行

    1. 首先我们实现一个方法,用于动态加载函数
    //动态加载方法
    //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);
    }
    
    1. 然后编写测试用例:
    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<对象名,对象>
        @Before
        public 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执行引擎
        @Test
        public void TestFunctionMethod(){
            String expression="user.getId().equals(id)";
            boolean res = (boolean) invokeMethod(expression,env);
            Assert.assertTrue(res);
        }
    }
    
    

    执行结果为true

    与Aviator相比,我们省去了修改表达式的步骤

  • 相关阅读:
    HTMLDOM
    换行
    【iOS】APP之数据存储
    开启远程XUL
    iOS之Streams
    Plugin的生命周期
    ActiveX Control Test Container
    ObjectiveC Runtime III【objc_msgSend函数】
    What is a Digital Signature?
    JS变量作用域
  • 原文地址:https://www.cnblogs.com/theory/p/13437571.html
Copyright © 2020-2023  润新知