Spring Boot 作为 Java 生态中最流行的开发框架,支持多种表达式引擎,如 SpEL(Spring Expression Language)、MVEL、Aviator 等,每种引擎在性能、语法复杂度、适用场景上各有优劣。例如:
2.1 SpEL表达式
SpEL(Spring Expression Language)是Spring框架的强劲表达式语言,支持在运行时查询和操作对象图。它语法简洁灵活,可进行属性访问、方法调用、算术运算、集合操作等,广泛应用于配置管理、条件注入等场景,提升开发效率。如下代码示例:
@RestController
public class SpELController {
@GetMapping("/spel")
public String evaluate() {
ExpressionParser parser = new SpelExpressionParser();
// 基本运算
Expression exp1 = parser.parseExpression("2 * 3 + 5");
int result1 = exp1.getValue(Integer.class);
// 字符串操作
Expression exp2 = parser.parseExpression("'SPEL'.toLowerCase()");
String result2 = exp2.getValue(String.class);
// 集合操作
Expression exp3 = parser.parseExpression("{1,2,3,4}.?[#this > 2]");
Object result3 = exp3.getValue();
return String.format("""
SpEL 结果:<br/>
基本运算: 2*3+5 = %d<br/>
字符串操作: 'SPEL'.toLowerCase() = %s<br/>
集合过滤: {1,2,3,4}.?[#this > 2] = %s<br/>
""", result1, result2, result3);
}
}运行结果

优点:
缺点:
2.2 MVEL
MVEL(MVFLEX Expression Language)是一种基于Java的轻量级表达式语言,语法简洁易读,支持算术、逻辑、字符串操作等。它可与Java无缝集成,动态解析执行表达式,适用于规则引擎、模板引擎等场景,能提升开发效率与代码灵活性。
引入依赖:
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.5.2.Final</version>
</dependency>如下示例:
@RestController
public class MVELController {
@GetMapping("/mvel")
public String evaluate() {
// 编译表达式提高性能
Serializable exp1 = MVEL.compileExpression("a * b + c");
Map<String, Object> vars = new HashMap<>();
vars.put("a", 5);
vars.put("b", 3);
vars.put("c", 2);
int result1 = MVEL.executeExpression(exp1, vars, Integer.class);
// 复杂逻辑
String exp2 = "if (x > y) { x * 2 } else { y * 3 }";
vars.put("x", 8);
vars.put("y", 10);
int result2 = MVEL.eval(exp2, vars, Integer.class);
// 集合操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Map<String, Object> vars1 = new HashMap<>();
vars1.put("list", list);
// 使用 MVEL 表达式进行过滤并求和
String exp = "sum = 0; for (n : list) { if (n % 2 == 0) sum += n }; sum";
Integer result3 = (Integer) MVEL.eval(exp, vars1);
return String.format("""
MVEL 结果:<br/>
基本运算: a*b+c = %d<br/>
条件逻辑: if (x>y) x*2 else y*3 = %d<br/>
集合操作: 偶数和 = %d
""", result1, result2, result3);
}
}运行结果

优点:
语法简洁、集成方便、执行效率较高,适合用于规则引擎、动态配置等场景。它支持类型推断、集合操作和部分函数式编程特性,与 Spring 等框架有良好集成。
缺点:
它并不完全支持 Java 语法,特别是对 Stream API 不兼容?,容易造成误解和使用障碍。对复杂逻辑支持较弱,调试和错误提示不够友善。
2.3 Aviator
Aviator是一个高性能、轻量级的Java表达式求值引擎。它支持数学运算、逻辑运算等,能将表达式编译成Java字节码执行,性能优越。还提供简洁API与丰富语法,支持自定义函数,可灵活集成到Java项目中,满足动态计算等需求。
引入依赖:
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.4.3</version>
</dependency>如下示例:
@RestController
public class AviatorController {
@GetMapping("/aviator")
public String evaluate() {
// 基本运算
Double result1 = (Double) AviatorEvaluator.execute("2 ** 10 + math.sqrt(100)");
// 使用变量
Map<String, Object> env = new HashMap<>();
env.put("name", "Aviator");
env.put("score", 95.5);
String result2 = (String) AviatorEvaluator.execute("name + ' score: ' + score", env);
// 大数运算
String result3 = AviatorEvaluator.execute("999999999999999999 * 888888888888888888").toString();
// 自定义函数
AviatorEvaluator.addFunction(new CustomFunction());
Double result4 = (Double) AviatorEvaluator.execute("square_root(144)");
return String.format("""
Aviator 结果:<br/>
基本运算: 2^10 + sqrt(100) = %s<br/>
变量使用: %s<br/>
大数运算: 999... * 888... = %s<br/>
自定义函数: square_root(144) = %s
""", result1, result2, result3, result4);
}
static class CustomFunction extends com.googlecode.aviator.runtime.function.AbstractFunction {
private static final long serialVersionUID = 1L;
@Override
public String getName() {
return "square_root";
}
@Override
public com.googlecode.aviator.runtime.type.AviatorObject call(Map<String, Object> env,
com.googlecode.aviator.runtime.type.AviatorObject arg1) {
Long num = (Long) arg1.getValue(env);
return new com.googlecode.aviator.runtime.type.AviatorDouble(Math.sqrt(num));
}
}
}运行结果

优点:
缺点:
2.4 JEP
JEP是Java Expression Parser(Java表达式分析器)的简称,是用于转换和计算数学表达式的Java库,支持自定义变量、常量和函数,能快速求值。
引入依赖:
<dependency>
<groupId>org.scijava</groupId>
<artifactId>jep</artifactId>
<version>2.4.2</version>
</dependency>代码示例:
@RestController
public class JEPController {
@GetMapping("/jep")
public String evaluate() {
JEP jep = new JEP() ;
jep.addStandardFunctions();
jep.addStandardConstants();
// 基本数学运算
jep.parseExpression("sin(pi/2) + log(100)") ;
double result1 = jep.getValue();
// 多变量计算
jep.addVariable("x", 3);
jep.addVariable("y", 4);
jep.parseExpression("x^2 + y^2");
double result2 = jep.getValue();
return String.format("""
JEP 结果:<br/>
三角函数: sin(π/2) + log(100) = %.1f<br/>
多变量: x² + y² = %.1f
""", result1, result2);
}
}运行结果

JEP超级使用数学运算,详细可以查看上面 addStandardFunctions 方法中添加的默认函数功能。
2.5 Ognl
OGNL 是一种功能强劲的表达式语言,用于访问和操作 Java 对象图。它支持属性导航、方法调用、集合投影/过滤、Lambda 表达式等,广泛应用于 Struts2 等框架。通过简洁语法(如 obj.property 或 collection.{property}),可高效操作复杂对象结构,简化数据绑定与逻辑处理。
引入依赖:
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.4.7</version>
</dependency>示例代码:
@RestController
public class OGNLController {
public static class User {
public String name;
public Address address;
public User(String name, Address address) {
this.name = name;
this.address = address;
}
}
public static class Address {
public String city;
public String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
}
@GetMapping("/ognl")
public String evaluate() throws OgnlException {
User user = new User("Tom", new Address("Beijing", "Chang'an Street"));
// 对象图导航
String city = (String) Ognl.getValue("address.city", user);
// 方法调用
String upperName = (String) Ognl.getValue("name.toUpperCase()", user);
// 集合投影
List<User> users = List.of(
new User("Alice", new Address("Shanghai", "Nanjing Road")),
new User("Bob", new Address("Guangzhou", "Zhongshan Road"))
);
OgnlContext context = (OgnlContext) Ognl.createDefaultContext(users);
context.put("users", users);
// 使用OGNL表达式进行投影操作,获取所有人的年龄
String expression = "#users.{name}";
Object names = Ognl.getValue(expression, context, context.getRoot());
return String.format("""
OGNL 结果:<br/>
对象导航: address.city = %s<br/>
方法调用: name.toUpperCase() = %s<br/>
集合投影: users.{name} = %s
""", city, upperName, names);
}
}运行结果

优点:
缺点:
2.6 JEXL
JEXL 实现了一种基于 JSTL(JavaServer Pages Standard Tag Library)表达式语言扩展的表达式语言,支持 shell 脚本或 ECMAScript 中常见的大部分结构。其目标是向在企业平台上工作的技术人员或顾问暴露可用的脚本功能。在许多使用场景中,JEXL 允许应用程序的最终用户编写自己的脚本或表达式,并确保这些脚本或表达式在受控的功能约束范围内执行。
引入依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl3</artifactId>
<version>3.5.0</version>
</dependency>示例代码:
@RestController
public class JEXLController {
@GetMapping("/jexl")
public String evaluate() {
JexlEngine jexl = new JexlBuilder().create();
// 简单表达式
JexlExpression exp1 = jexl.createExpression("'Hello ' + name");
JexlContext context1 = new MapContext();
context1.set("name", "JEXL");
String result1 = exp1.evaluate(context1).toString(); // "Hello JEXL"
// 条件判断
JexlExpression exp2 = jexl.createExpression("age >= 18 ? 'Adult' : 'Minor'");
JexlContext context2 = new MapContext();
context2.set("age", 20);
String result2 = exp2.evaluate(context2).toString(); // "Adult"
// 循环操作
JexlScript script = jexl.createScript("""
total = 0;
for (n : numbers) {
total += n
}
return total
""");
JexlContext context3 = new MapContext();
context3.set("numbers", new int[] { 1, 2, 3, 4, 5 });
Object result3 = script.execute(context3); // 15
return String.format("""
JEXL 结果:<br/>
字符串拼接: %s<br/>
条件判断: %s<br/>
循环求和: %d
""", result1, result2, result3);
}
}运行结果

优点:
缺点: