方法调用: '#{myBean.myMethod(args)}'- 三元运算符: '#{condition ? trueValue : falseValue}'
- 列表和数组访问: '#{myList[0]}'
- 算术运算: '#{2+3}'
spel工具类
public class SpringExpressionUtil {
private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
private SpringExpressionUtil(){}
/**
* Evaluates the given Spring EL expression against the provided root object.
*
* @param rootObject The object to use as the root of the expression evaluation.
* @param expressionString The Spring EL expression to evaluate.
* @param returnType The expected return type.
* @return The result of the expression evaluation.
*/
public static T evaluateExpression(Map rootObject, String expressionString, Class returnType) {
StandardEvaluationContext context = new StandardEvaluationContext(rootObject);
rootObject.forEach(context::setVariable);
return EXPRESSION_PARSER.parseExpression(expressionString).getValue(context,returnType);
}
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("name","lybgeek");
map.put("hello","world");
System.out.println(evaluateExpression(map,"#root.get('name')",String.class));
}
}
2、ognl
官方文档
https://ognl.orphan.software/language-guide
官方示例
https://github.com/orphan-oss/ognl
OGNL (Object-Graph Navigation Language) 是一个强大的表达式语言,用于获取和设置Java对象的属性。它在许多Java框架中被用作数据绑定和操作对象图的工具,最著名的应用是在Apache Struts2框架中。以下是关于OGNL的一些关键特性:
简单表达式: OGNL允许你以简单的字符串形式编写表达式来访问对象属性,如person.name就可以获取person对象的name属性。
链式导航: 支持链式调用来深入对象图,例如customer.address.street会依次导航到customer的address属性,再从address获取street。
集合操作: OGNL可以直接在表达式中处理集合和数组,包括遍历、筛选、投影等操作,如customers.{name}可以获取所有customers集合中每个元素的name属性。
上下文敏感: OGNL表达式解析时会考虑一个上下文环境,这个环境包含了变量、对象和其他表达式可能需要的信息。
方法调用与构造器: 除了属性访问,OGNL还支持调用对象的方法和构造新对象,如@myUtil.trim(name)调用工具类方法,或new java.util.Date()创建新对象。
条件与逻辑运算: 支持if、else逻辑,以及&&、||等逻辑运算符,使得表达式可以处理更复杂的逻辑判断。
变量赋值: OGNL不仅能够读取数据,还能设置对象属性的值,如person.name = "Alice"。
安全问题: 和SpEL一样,使用OGNL时也需注意表达式注入的安全风险,确保用户输入不会被直接用于构造表达式,以防止恶意操作。
OGNL以其简洁的语法和强大的功能,在处理对象关系和数据绑定方面非常实用,尤其是在需要动态操作对象和集合的场景下。
ognl工具类
public class OgnlExpressionUtil {
private OgnlExpressionUtil(){}
/**
* Evaluates the given Ognl EL expression against the provided root object.
*
* @param rootObject The object to use as the root of the expression evaluation.
* @param expressionString The OGNL EL expression to evaluate.
* @param returnType The expected return type.
* @return The result of the expression evaluation.
*/
public static T evaluateExpression(Map rootObject, String expressionString, Class returnType) {
Object value = OgnlCache.getValue(expressionString, rootObject);
if(value != null && value.getClass().isAssignableFrom(returnType)){
return (T)value;
}
return null;
}
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("name","lybgeek");
map.put("hello","world");
System.out.println(OgnlExpressionUtil.evaluateExpression(map,"#root.name",String.class));
System.out.println(SpringExpressionUtil.evaluateExpression(map,"#root.get('hello')",String.class));
}
}
3、Aviator
官方文档
http://fnil.net/aviator/
官方示例
https://github.com/killme2008/aviatorscript
Aviator是一个轻量级的Java表达式执行引擎,它设计用于高性能的动态计算场景,特别是那些需要在运行时解析和执行复杂表达式的应用场景。以下是Aviator的一些核心特点和功能:
高性能: Aviator优化了表达式的编译和执行过程,特别适合于对性能有严格要求的系统,如金融风控、实时计算等领域。
易于集成: 提供简单的API接口,使得在Java项目中嵌入Aviator变得非常容易,只需引入依赖,即可开始编写和执行表达式。
丰富的表达式支持: 支持数学运算、逻辑运算、比较运算、位运算、字符串操作、三元运算、变量定义与引用、函数调用等,几乎覆盖了所有常见的运算需求。
安全沙箱模式: Aviator提供了沙箱机制,可以限制表达式的执行权限,比如禁止访问某些方法或字段,从而提高应用的安全性。
动态脚本执行: 允许在运行时动态加载和执行脚本,非常适合用于规则引擎、配置驱动的系统逻辑等场景。
JIT编译: Aviator采用即时编译技术,将表达式编译成Java字节码执行,进一步提升执行效率。
数据绑定: 可以方便地将Java对象、Map、List等数据结构绑定到表达式上下文中,实现表达式与Java数据的无缝对接。
扩展性: 支持自定义函数,用户可以根据需要扩展Aviator的功能,增加特定业务逻辑的处理能力。
Aviator因其高性能和灵活性,在需要动态脚本处理的场景中,特别是在那些对性能敏感且需要频繁执行复杂计算逻辑的应用中,是一个非常有吸引力的选择。
Aviator工具类
public final class AviatorExpressionUtil {
private AviatorExpressionUtil() {
}
/**
* 执行Aviator表达式并返回结果
*
* @param expression Aviator表达式字符串
* @param env 上下文环境,可以包含变量和函数
* @return 表达式计算后的结果
*/
public static T evaluateExpression(Map env,String expression, Class returnType) {
Object value = AviatorEvaluator.execute(expression, env);
if(value != null && value.getClass().isAssignableFrom(returnType)){
return (T)value;
}
return null;
}
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("name","lybgeek");
map.put("hello","world");
Map env = new HashMap<>();
env.put("root",map);
System.out.println(evaluateExpression(env,"#root.name",String.class));
}
}
4、Mvel2
官方文档
mvel.documentnode.com/
官方示例
https://github.com/mvel/mvel
MVEL2(MVFLEX Expression Language 2)是一种强大且灵活的Java库,用于解析和执行表达式语言。它是MVEL项目的第二代版本,旨在提供高效、简洁的方式来操作对象和执行逻辑。下面是关于MVEL2的一些关键特性和使用指南:
动态类型与静态类型混合: MVEL支持动态类型,同时也允许静态类型检查,这意味着你可以选择是否在编译时检查类型错误,增加了灵活性和安全性。
简洁的语法: MVEL语法基于Java但更加简洁,便于编写和阅读,适用于快速构建表达式和小型脚本。
属性访问与方法调用: 类似于其他表达式语言,MVEL允许直接访问对象属性和调用其方法,如person.name或list.size()。
控制流语句: 支持if、else、switch、循环(for、while)等控制流结构,使得在表达式中实现复杂逻辑成为可能。
模板引擎: MVEL2提供了一个强大的模板引擎,可以用来生成文本输出,类似于Velocity或Freemarker,但与MVEL表达式无缝集成。
变量赋值与函数定义: 直接在表达式中定义变量和函数,支持局部变量和闭包(匿名函数)。
数据绑定与转换: 自动或手动进行类型转换,简化了不同数据类型间的操作。
集成与扩展: MVEL设计为易于集成到现有Java项目中,同时提供了扩展点,允许用户定义自定义函数和操作符。
性能优化: MVEL关注执行效率,通过优化的编译器和执行引擎来减少运行时开销。
5、Hutool表达式引擎门面
官方文档
https://doc.hutool.cn/pages/ExpressionUtil/#介绍
hutool工具包在5.5.0版本之后,提供了表达式计算引擎封装为门面模式,提供统一的API,去除差异。目前支持如下表达式引擎
- Aviator
- Apache Jexl3
- MVEL
- JfireEL
- Rhino
- Spring Expression Language
(SpEL)
如上所述的表达式引擎不能满足要求,hutool还支持通过SPI进行自定义扩展
基于hutool封装的工具类
public class HutoolExpressionUtil {
private HutoolExpressionUtil(){}
/**
* 执行表达式并返回结果。
*
* @param expression 表达式字符串
* @param variables 变量映射,键为变量名,值为变量值
* @return 表达式计算后的结果
*/
public static T evaluateExpression(Map variables,String expression, Class returnType) {
try {
Object value = ExpressionUtil.eval(expression, variables);
if(value != null && value.getClass().isAssignableFrom(returnType)){
return (T)value;
}
} catch (Exception e) {
throw new RuntimeException("Error executing expression: " + expression, e);
}
return null;
}
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("name","lybgeek");
map.put("hello","world");
Map variables = new HashMap<>();
variables.put("root",map);
System.out.println(evaluateExpression(variables,"root.name",String.class));
}
}
总结
本文介绍了市面比较常用的表达式引擎组件,而这些引擎基本上都可以用hutool提供的表达式门面实现,hutool确实在工具类这方面做得很好,基本上我们日常会用到的工具,它大部分都涵盖到。最后文末demo链接,也提供了跟spring整合的表达引擎聚合实现,大家感兴趣也可以看看。
demo链接
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-el
本文暂时没有评论,来添加一个吧(●'◡'●)