在 Java 开发中,经常需要处理动态逻辑、规则计算或配置解析。硬编码这些逻辑缺乏灵活性,而 MVEL (MVFLEX Expression Language) 作为一款高性能、功能丰富的表达式引擎,可以很好的解决这类问题。
MVEL
1、MVEL 简介
MVEL 是一种基于 Java 的动态表达式语言和运行时。它不仅仅是一个简单的属性提取工具(如 OGNL),更是一个强大的脚本引擎。其核心优势在于:
高性能: 采用解释和编译两种执行模式,编译后执行速度接近原生 Java。
功能强大: 支持完整的控制流语句 (if, for, while)、赋值、函数调用、集合操作、正则表达式、投影/收集等。
语法简洁: 借鉴 Java 语法,易于学习,表达式直观易读。
灵活集成: 易于嵌入到 Java 应用程序中,与各种框架(如规则引擎 Drools, 模板引擎)无缝协作。
强类型与弱类型结合: 支持类型推断,也允许动态类型操作。
应用广泛: 规则引擎中的条件/动作、动态配置解析、模板渲染(如邮件模板)、简单脚本任务、数据映射转换等。
为什么选择 MVEL?
相比 java.util.regex 或字符串切割,它能处理更复杂的逻辑。
相比完整的脚本引擎(如 Groovy),它更轻量级,启动更快,安全性控制更直接。
相比 OGNL、SpEL (Spring Expression Language),它在复杂脚本和性能(尤其是编译模式)方面通常更有优势。
2、MVEL使用
将 MVEL 集成到Java 项目非常简单,引入maven依赖:
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.4.14.Final</version>
</dependency>
2.1、执行表达式
可以很方便的执行一些算术表达式:
public class MvelTest {
public static void main(String[] args) {
String expression = "2 + 3 * 4";
Object result = MVEL.eval(expression);
System.out.println("Result: " + result);
}
}
2.2、变量绑定与执行上下文
可以将变量传入表达式执行环境:
public class MvelTest {
public static void main(String[] args) {
String expression = "x + y";
Map<String, Integer> variables = new HashMap<>(4);
variables.put("x", 2);
variables.put("y", 3);
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
2.3、执行脚本
MVEL 可以执行包含复杂逻辑的脚本块,如if-else语句、foreach语句等
public class MvelTest {
public static void main(String[] args) {
String expression = "if (x > y) { x } else { y }";
Map<String, Object> variables = new HashMap<>(4);
variables.put("x", 2);
variables.put("y", 3);
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
使用foreach语句
public class MvelTest {
public static void main(String[] args) {
String expression = "foreach (item : list) { System.out.print(item) }";
Map<String, Object> variables = new HashMap<>(2);
variables.put("list", Arrays.asList(1, 2, 3, 4, 5));
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
2.4、对象操作
public class MvelTest {
public static void main(String[] args) {
String expression = "person.name + ' ' + person.age";
Map<String, Object> variables = new HashMap<>(2);
variables.put("person", new Person("John", 30));
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
private static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
}
2.5、集合操作
public class MvelTest {
public static void main(String[] args) {
String expression = "list.size()";
Map<String, Object> variables = new HashMap<>(2);
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
variables.put("list", list);
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
2.6、使用函数
public class MvelTest {
public static void main(String[] args) {
String expression = "Math.pow(x, y)";
Map<String, Object> variables = new HashMap<>();
variables.put("x", 2);
variables.put("y", 3);
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
2.7、使用自定义函数
public class MvelTest {
public static void main(String[] args) {
String expression = "myFunction(x, y)";
Map<String, Object> variables = new HashMap<>();
variables.put("x", 2);
variables.put("y", 3);
variables.put("myFunction", new MyFunction());
Object result = MVEL.eval(expression, variables);
}
private static class MyFunction {
public double myFunction(double x, double y) {
return Math.pow(x, y);
}
}
}
2.8、使用自定义类
public class MvelTest {
public static void main(String[] args) {
String expression = "cn.river.base.mvel.StringUtils.reverse(s)";
Map<String, Object> variables = new HashMap<>();
variables.put("s", "Hello, World!");
Object result = MVEL.eval(expression, variables);
System.out.println("Result: " + result);
}
}
public class StringUtils {
public static String reverse(String s) {
return new StringBuilder(s).reverse().toString();
}
}
2.9、编译与执行 (提升性能)
对于需要重复执行的表达式,先编译再执行效率更高:
public class MvelTest {
public static void main(String[] args) {
String expression = "x + y * 10";
Map<String, Object> variables = new HashMap<>(4);
variables.put("x", 2);
variables.put("y", 3);
Serializable serializable = MVEL.compileExpression(expression);
Object result = MVEL.executeExpression(serializable, variables);
System.out.println("Result: " + result);
}
}
MVEL.compileExpression(string)是将表达式编译成MVEL可执行的内容,然后通过MVEL.executeExpression(expression)执行。编译后的表达式可以缓存起来,下次直接执行,减少编译时间,提升性能。
3、结语
MVEL以其高性能、丰富的功能和简洁的语法,成为Java生态中处理动态表达式和脚本任务的首选工具之一。无论是简单的属性提取、条件判断,还是包含循环和赋值的复杂脚本逻辑,MVEL 都能轻松胜任。如果你正在寻找一个功能强大且不臃肿的表达式引擎,不妨尝试下MVEL。