表达式解析器Mvel2.0(MVFLEX Expression Language)

Posted 双斜杠少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表达式解析器Mvel2.0(MVFLEX Expression Language)相关的知识,希望对你有一定的参考价值。

时间过的好快,突然就发现,已经过去一两年了,这一两年博客也写的不多,快要进入中年了,最重要的就是自律。要好好睡觉,好好学习,好好工作。

废话不多说,这次给大家说的是 表达式语言解析Mvel2.0

简介

MVEL为 MVFLEX Expression Language(MVFLEX表达式语言)的缩写,它是一种动态/静态的可嵌入的表达式语言和为Java平台提供Runtime(运行时)的语言。最初是作为一个应用程序框架实用程序的语言开始,该项目现已发展完全独立。

MVEL通常用于执行用户(程序员)通过配置XML文件或注释等定义的基本逻辑。它也可以用来解析简单的JavaBean表达式。Runtime(运行时)允许MVEL表达式通过解释执行或者预编译生成字节码后执行。

MVEL可以和drools 规则引擎配合使用

2.0版本,具有以下特性:

  1. 动态JIT优化器。当负载超过一个确保代码产生的阈值时,选择性地产生字节代码,这大大减少了内存的使用量。

新的静态类型检查和属性支持,允许集成类型安全表达。

  1. 错误报告的改善。包括行和列的错误信息。

  2. 新的脚本语言特征。MVEL2.0 包含函数定义,如:闭包,lambda定义,标准循环构造(for, while, do-while, do-until…),空值安全导航操作,内联with-context运营 ,易变的(isdef)的测试运营等等。

  3. 改进的集成功能。迎合主流的需求,MVEL2.0支持基础类型的个性化属性处理器,集成到JIT中。

  4. 更快的模板引擎,支持线性模板定义,宏定义和个性化标记定义。

  5. 新的交互式shell(MVELSH)。

mvel 与ognl,Groovy 表达式语言的性能对比结果

1:目前:MVEL拥有最快的解析器和编译器
2:MVEL优于其他嵌入式脚本语言的所有基准,除了算术性能基准方面:JEXL和MVEL并列( 12ms操作50000次迭代) 。
3:Groovy的编译器最慢,其次是JUEL然后OGNL 。
4:OGNL最差缓存反射性能,其次是JEXL 。
5:OGNL的嵌套map基准表现最差。这个基准包括解决从使用索引语法的Map中获取属性的问题(foo[‘bar’][‘something’]) 。
6:Groovy的编译器是目前使用一个特设的方式的时候速度太慢。

代码时刻

mvel2.x表达式包含以下部分的内容:属性表达式,布尔表达式,方法调用,变量赋值,函数定义。

我这边是做规则判断时用到此表达式语言,所以将自己用到的情况及例子贴出来。关于mvel 其他的一些用途和功能,大家可以下载文末的 mvel2.0文档,自行进行学习。

首先引入依赖

 <dependency>
            <groupId>org.mvel</groupId>
            <artifactId>mvel2</artifactId>
            <version>2.4.7.Final</version>
        </dependency>

创建mvel引擎对象和方法

import java.io.Serializable;
import java.util.Map;

import org.mvel2.MVEL;

/**
 * 脚本语言性能测试结果
 * https://www.iteye.com/topic/361794
 * https://www.iteye.com/blog/caoyaojun1988-163-com-2089726
 *
 * @author yyb
 * @time 2020/8/12
 */
public class MvelEngine 


    /**
     * 执行表达式
     *
     * @param expr
     * @param data
     * @return
     */
    public Object exec(String expr, Map<String, Object> data) 
        try 
            Object result = MVEL.eval(expr, data);
            if (result != null) 
                return result;
            
         catch (Exception e) 
            System.out.println("表达式执行错误");
            return false;
        
        return null;

    

    /**
     * 编译表达式
     *
     * @param expr
     * @return
     */
    public Serializable compileExpr(String expr) 
        try 
            Serializable compiled = MVEL.compileExpression(expr);
            return compiled;
         catch (Exception e) 
            System.out.println("表达式编译错误:" + expr);
            return null;
        
    

    /**
     * 执行编译后的表达式
     *
     * @param expr
     * @param data
     * @return
     */
    public boolean execCompiled(Object expr, Map<String, Object> data) 
        try 
            Object result = MVEL.executeExpression(expr, data);
            if (result instanceof Boolean) 
                return (Boolean) result;
             else 
                return false;
            
         catch (Exception e) 
            System.out.println("表达式执行错误");
            return false;
        
    

    /**
     * 执行有返回值的表达式
     *
     * @param expr
     * @param data
     * @return
     */
    public Object execReturnCompiled(Object expr, Map<String, Object> data) 
        try 
            Object result = MVEL.executeExpression(expr, data);
            if (result != null) 
                return result;
            
         catch (Exception e) 
            System.out.println("表达式执行错误");
            return false;
        
        return null;
    


    private static MvelEngine engine;

    /**
     * 创建基于MVEL的表达式引擎。
     *
     * @return
     */
    public synchronized static MvelEngine defaultEngine() 
        if (engine == null) 
            engine = new MvelEngine();
        
        return engine;
    

测试代码


public class MvelTest 

    public static void main(String[] args) 
        ageTest();
        containsTest();
        startsWithTest();
        emptyTest();
        multipleTest();
        returnTest();
        execExprTest();


    


    /**
     * 布尔表达式:
     * 大于小于 等于 以及 优先级
     */
    public static void ageTest() 
        String expr = "(age > 10 && age <= 20) || age == 11 ";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("age", 12);
        if (engine.execCompiled(obj, params)) 
            //满足表达式
            System.out.println("少年");
         else 
            System.out.println("不满足条件");
        
    


    /**
     * 判断包含
     */
    public static void containsTest() 
        String expr = "name contains(\\"张\\")";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("name", "张三");
        params.put("age", 11);
        if (engine.execCompiled(obj, params)) 
            //满足表达式
            System.out.println("包含张");
         else 
            System.out.println("不满足条件");
        
    

    /**
     * 判断以xx开头
     */
    public static void startsWithTest() 
        String expr = "mobile.startsWith(136)";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("mobile", "13643489802");
        params.put("age", 11);
        if (engine.execCompiled(obj, params)) 
            //满足表达式
            System.out.println("包含136开头手机号");
         else 
            System.out.println("不满足条件");
        
    

    /**
     * 判空,多个表达式时,只有最后一个表达式的结果为返回
     */
    public static void emptyTest() 
        String expr = "foo == null ; foo1 == nil; foo2 == empty";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("foo", 1);
        params.put("foo1", 1);
        params.put("foo2", " ");
        if (engine.execCompiled(obj, params)) 
            //满足表达式
            System.out.println("true");
         else 
            System.out.println("不满足条件");
        
    


    /**
     * 多个表达式时,只有最后一个表达式的结果为返回
     * 您可以编写具有任意数量语句的脚本,使用分号表示语句的终止。这在所有情况下都是必需的,除非只有一条语句,或者脚本中的最后一条语句。
     */
    public static void multipleTest() 
        String expr = "age > 20; sex == 1; name contains(\\"张2\\")";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("age", 10);
        params.put("sex", 1);
        params.put("name", "张三");
        if (engine.execCompiled(obj, params)) 
            //满足表达式
            System.out.println("true");
         else 
            System.out.println("不满足条件");
        
    

    /**
     * 有返回值的表达式
     */
    public static void returnTest() 
        String expr = "a = 10;b = (a = a * 2) + 10; a;";
        MvelEngine engine = MvelEngine.defaultEngine();
        Object obj = engine.compileExpr(expr);
        Map<String, Object> params = new HashedMap();
        params.put("a", 1);
        Object r = engine.execReturnCompiled(obj, params);
        if (null != r) 
            //满足表达式
            System.out.println("a = " + r);
         else 
            System.out.println("不满足条件");
        
    

    /**
     * 不用编辑即可执行
     */
    public static void execExprTest() 
        String expr = "x * y";
        MvelEngine engine = MvelEngine.defaultEngine();
        Map vars = new HashMap();
        vars.put("x", new Integer(5));
        vars.put("y", new Integer(10));
        Object r = engine.exec(expr, vars);
        if (r != null) 
            //满足表达式
            System.out.println(r);
         else 
            System.out.println("不满足条件");
        
    



mvel2.0语法指南文档点我下载

参考资料

https://blog.csdn.net/shichen2010/article/details/78466293

http://mvel.codehaus.org/

https://www.iteye.com/topic/361794

以上是关于表达式解析器Mvel2.0(MVFLEX Expression Language)的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式解析警报“expr”时出错

[ jquery 过滤器 parents(expr) ] 此方法用于在选择器的基础之上搜索被选元素沿着父元素链找到符合参数的那个父元素,完成需求,如果没有参数,他会一直沿着父元素链解析到 html 标

在 C# 中解析骰子表达式(例如 3d6+5):从哪里开始?

ANTLR快餐教程 - ANTLR其实很简单

JavaScript 如何解析链式三元表达式?

MySQL基础入门学习查询表达式解析 SELECT