Mvel是一种易于使用、灵活且强大的表达式解析器,语法与java有些相似,功能有点像是将我们的自然语言解析为计算机语言(个人通俗理解,不准确)。

基础使用

文档:http://mvel.documentnode.com/#language-guide-for-2.0

举个最简单的例子:

要判断 5 是否大于 2,  或者计算 5减2这种算术运算, 直接用下面代码中写法即可

import org.mvel2.MVEL;
import org.mvel2.ParserContext;

import java.io.Serializable;

/**
 * Mvel测试
 *
 * @author: Danger
 */
public class MvelTest {

    public static void main(String[] args) {
        System.out.println(MVEL.eval("5 > 2"));
        System.out.println(MVEL.eval("5 - 2"));

        Serializable expression = MVEL.compileExpression("5 + 2");
        Object result = MVEL.executeExpression(expression);
        System.out.println(result);

        Object result2 = MVEL.executeExpression(MVEL.compileExpression("[1, 2, 3] contains 2"));
        System.out.println(result2);

    }
}

其中, MVEL.compileExpression(string)是将表达式编译成mvel可执行的内容,然后通过MVEL.executeExpression(expression)执行。

Mvel表达式是默认支持一些方法的,像是上面例子中用到算术运算、list的contains方法等,同时也支持自定义方法。

自定义方法

某些场景我们需要更复杂的运算或者处理逻辑,这时候可以使用自定义方法。

大致流程:

1. 自定义方法

2. 将自定义方法添加到Mvel的ParserContext中

3. 基于ParserContext环境 编译和执行Mvel表达式

代码如下:

import org.apache.commons.lang3.StringUtils;

/**
 * 用户自定义方法
 *
 * @author: Danger
 */
public class UserFunction {

    /**
     * 字符串source 是否包含 target, 忽略大小写
     *
     * @param source
     * @param target
     * @return boolean
     */
    public static boolean containsIgnCase(String source, String target) {
        if (StringUtils.isEmpty(source) || StringUtils.isEmpty(target)) {
            return false;
        }
        if (source.toUpperCase().contains(target.toUpperCase())) {
            return true;
        }

        return false;
    }
}
import org.apache.commons.lang3.StringUtils;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;

import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * Mvel编译
 *
 * @author: Danger
 */
public class MvelCompiler {

    private static final MvelCompiler instance = new MvelCompiler();

    private static ParserContext context;

    private MvelCompiler() {
        context = new ParserContext();

        // 将UserFunction类中的所有方法加载到context中
        Method[] declaredMethods = UserFunction.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            context.addImport(declaredMethod.getName(), declaredMethod);
        }

        // 或者用下面这种一个个指定的方式加载到context中
//        context.addImport("containsIgnCase", MVEL.getStaticMethod(UserFunction.class, "containsIgnCase", new Class[]{String.class, String.class}));
    }

    public static MvelCompiler getInstance() {
        return instance;
    }

    public Serializable compile(String expression) {
        if (StringUtils.isNotEmpty(expression)) {
            return MVEL.compileExpression(expression, context);
        }

        return null;
    }
}

测试验证:

/**
 * Mvel测试
 *
 * @author: Danger
 */
public class MvelTest {

    public static void main(String[] args) {
        ParserContext parserContext = new ParserContext();
        parserContext.addImport("containsIgnCase", MVEL.getStaticMethod(UserFunction.class, "containsIgnCase", new Class[]{String.class, String.class}));
        Serializable expression1 = MVEL.compileExpression("containsIgnCase('abc', 'BC')", parserContext);
        Object result3 = MVEL.executeExpression(expression1);
        System.out.println(result3);

        Object result4 = MVEL.executeExpression(MvelCompiler.getInstance().compile("containsIgnCase('abc', 'D')"));
        System.out.println(result4);
    }
}

 

以上。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐