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);
}
}
以上。