聊聊我们那些年用过的表达式引擎组件

news/2024/11/14 4:41:06/文章来源:https://www.cnblogs.com/linyb-geek/p/18242275

前言

我们在设计一些表单或者流程引擎时,可能我们会设计各种各样的表达式或者规则,我们通过各种表达式或者规则来实现我们的业务流转。今天就来盘点一下我们经常会使用到的表达式引擎

常用表达式引擎

1、spring el

官方文档

https://docs.spring.io/spring-framework/reference/core/expressions.html

官方示例
https://github.com/spring-projects/spring-framework/tree/master/spring-expression

Spring Expression Language (SpEL) 是Spring框架中的一个强大的表达式语言,用于在运行时查询和操作对象图。以下是关于Spring EL的几个关键点:

动态查询和操作: SpEL允许你在运行时执行复杂的查询和操作数据,比如读取bean的属性值、调用方法、进行算术运算、逻辑判断等。
集成于Spring框架: SpEL广泛应用于Spring的各种模块中,如Spring Security的访问控制表达式、Spring Data的查询条件定义、Spring Integration的消息路由等。
基本语法: SpEL表达式通常被包含在#{...}中,例如#{property}用来获取一个bean的属性值。它支持字符串、布尔、算术、关系、逻辑运算符,以及方法调用、数组和列表索引访问等。
上下文感知: SpEL能够访问Spring应用上下文中的Bean,这意味着你可以直接在表达式中引用配置的bean,实现高度灵活的配置和运行时行为调整。
类型转换: SpEL提供了内置的类型转换服务,可以自动或显式地将一种类型的值转换为另一种类型。
安全考量: 使用SpEL时需要注意安全性,避免注入攻击。Spring提供了ExpressionParser的配置来限制表达式的执行能力,如禁用方法调用或属性访问等。
例子:

  • 访问Bean属性: #
  • 方法调用: #
  • 三元运算符: #
  • 列表和数组访问: #
  • 算术运算: #

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> T evaluateExpression(Map<String, Object> rootObject, String expressionString, Class<T> 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<String,Object> 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> T evaluateExpression(Map<String, Object> rootObject, String expressionString, Class<T> 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<String,Object> 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> T evaluateExpression(Map<String, Object> env,String expression, Class<T> 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<String,Object> map = new HashMap<>();map.put("name","lybgeek");map.put("hello","world");Map<String,Object> 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> T evaluateExpression(Map<String, Object> variables,String expression, Class<T> 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<String,Object> map = new HashMap<>();map.put("name","lybgeek");map.put("hello","world");Map<String,Object> 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832167.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能是这样理解“情绪”的

前一篇:《人工智能模型训练:从不同格式文件中读取训练数据集》 前言:在前面的内容中,我们经常提到“特征”,那么如何表示特征呢?举个例子,在日常生活中,我们描述一个快递包装盒时可能会提到它的高度、宽度和深度(这三个值就是盒子的特征,当然也可以用颜色、重量、材料…

利用卷积神经网络(CNN)进行花朵分类任务

一、卷积神经网络 卷积神经网络(Convolutional Neural Netword,CNN)是一种深度学习模型,它在图像识别、视频分析、自然语言处理等领域表现出色。CNN 的核心思想是利用卷积运算来提取输入数据的特征,并且能够保持空间层次结构。 卷积神经网络的架构如下:我们今天的重点是利…

南沙C++信奥赛老师解一本通题 1385:团伙(group)

​ 【题目描述】在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1、我朋友的朋友是我的朋友; 2、我敌人的敌人是我的朋友; 所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这…

Docker:部署kkFileView所有格式文档在线预览服务

前言 kkFileView是一个文档在线预览服务,基本支持主流文档格式预览,目前支持的文件类型如下:支持 doc, docx, xls, xlsx, xlsm, ppt, pptx, csv, tsv, dotm, xlt, xltm, dot, dotx,xlam, xla 等 Office 办公文档 支持 wps, dps, et, ett, wpt 等国产 WPS Office 办公文档 支…

学校厕所防欺凌检测系统

学校厕所防欺凌检测系统通过在关键区域安装的音频和视频监控设备,学校厕所防欺凌检测系统实时捕捉现场的声音和画面。AI音频分析技术能够对前端音频进行实时处理,当系统识别到“救命”、“打架”、“老师快来”等敏感词汇时,会自动触发预警机制,联动值班老师或校园安全中心…

物流园区烟火烟雾检测系统

物流园区烟火烟雾检测系统通过在园区关键位置安装的高清摄像头,物流园区烟火烟雾检测系统实现对监控区域的无人值守和不间断工作。系统利用先进的AI视觉算法,能够主动发现监控区域内的烟雾和火灾苗头,并进行实时分析报警。与传统的火灾监测系统相比,该系统不需要依赖其他传…

错误代码的个人见解以及逻辑分析题

一、代码错误分析代码中的错误: 1.src 指针指向字符串字面值,不可修改: 字符串 "hello,world" 是存储在只读区域的常量字符串,不能通过指针直接修改。 如果需要倒序操作,需要把字符串复制到一个可修改的内存中。2.dest 未正确分配内存: 在 malloc(len) 时,没有…

docx 生成word报告

# -*- coding: utf-8 -*- import base64 import os from io import BytesIO from docx import Document from docx.shared import Inches, Pt from bs4 import BeautifulSoup from matplotlib import pyplot as plt from wordcloud import WordCloud # 设置全局字体 plt.rcPara…

leetcode算法题-有效的括号(简单)

有效的括号(简单) leetcode:https://leetcode.cn/problems/valid-parentheses/description/ 前言 防止脑袋生锈,做一下leetcode的简单算法题,难得也做不来哈哈。 大佬绕道,小白可看。 题目描述 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符…

30+企业高管齐聚!医疗器械企业渠道优化与健康增长主题沙龙成功举办

10月29日,深圳医疗器械行业协会携手纷享销客,共同举办了一场以“渠道优化与健康增长”为主题,探索医疗器械企业在新形势下渠道管理及落地实践的沙龙活动。此次活动吸引了33位医疗器械企业的管理层,共同探寻医疗器械企业营销增长的新思路、新渠道与新路径。<活动照片>…

AutoCAD Blockview .net在wpf项目中的问题

之前使用Blockview是遇到平移的问题, 这几天在学习使用CommunityToolkit.MVVM框架来创建用户界面, 当创建GsPreviewCtrl控件时会遇到错误, 导致整个窗体不能显示, 错误信息如下:************** 异常文本 ************** System.InvalidProgramException: 公共语言运行时检…

html`` - function html(str) { return str+111 } 调用方式 - solidjs文档里面发现的

html`` - function html(str) { return str+111 } 调用方式 标签模板字符串Tagged Template Literals 这里是自己实现这个字符串模板,等于函数调用的另一种方式 html(111) html`111`solidjs文档里面发现的 https://www.solidjs.com/guides/getting-started#不使用构建工具----…