Aviator 一种表达式求值引擎

2023-12-28 08:38

本文主要是介绍Aviator 一种表达式求值引擎,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.简介

Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢?
Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上依赖包也才 537K,不算依赖包的话只有 70K; 当然, Aviator的语法是受限的, 它不是一门完整的语言, 而只是语言的一小部分集合。
其次, Aviator的实现思路与其他轻量级的求值器很不相同, 其他求值器一般都是通过解释的方式运行, 而Aviator则是直接将表达式编译成 JVM 字节码, 交给 JVM 去执行。简单来说, Aviator的定位是介于 Groovy 这样的重量级脚本语言和 IKExpression 这样的轻量级表达式引擎之间。

2.特性

Aviator的特性:

  • 支持绝大多数运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式(? : );
  • 支持操作符优先级和括号强制设定优先级;
  • 逻辑运算符支持短路运算;
  • 支持丰富类型,例如nil、整数和浮点数、字符串、正则表达式、日期、变量等,支持自动类型转换;
  • 支持传入变量,支持类似a.b.c的嵌套变量访问;
  • 内置一套强大的常用函数库;
  • 可自定义函数,易于扩展;
  • 可重载操作符;
  • 支持大数运算(BigInteger)和高精度运算(BigDecimal);
  • 性能优秀。

Aviator的限制:

  • 没有if else、do while等语句,没有赋值语句,仅支持逻辑表达式、算术表达式、三元表达式和正则匹配。
  • 无法自定义运算符,自定义函数有局限性

3.依赖

Aviator依赖了commons-beanutils, 使用Aviator可以添加下面的maven依赖:

<dependency><groupId>com.googlecode.aviator</groupId><artifactId>aviator</artifactId><version>{version}</version></dependency>

从 3.2.0 版本开始, Aviator 仅支持 JDK 7 及其以上版本。 JDK 6 请使用 3.1.1 这个稳定版本。

4.使用手册

  1. 执行表达式
    Aviator的使用都是集中通过com.googlecode.aviator.AviatorEvaluator这个入口类来处理, 最简单的例子, 执行一个计算1+2+3的表达式:
val result = AviatorEvaluator.execute("1+2+3")
println(result)     //6

如果开启了 ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL 选项,那么在表达式中出现的浮点数都将解析为 BigDecimal,这是为了方便一些用户要求高精度的计算,又不想额外地给浮点数加上 M 后缀标记为 BigDecimal:

AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true)
  1. 多行表达式
    从 4.0.0 开始, aviator支持以分号 ; 隔开的多行表达式,对于多行表达式求值的结果将是最后一个表达式的结果,例如
val result = AviatorEvaluator.execute("println('hello world'); 1+2+3 ; 100-1")
println(result) 
//输出结果:
//hello world
//99

表达式的结果将是最后一个表达式 100-1,也就是 99,但是中间的表达式也将执行,包括打印 hello world。通过在表达式求值过程中加入 println打印,可以方便调试,也可以通过 Options.TRACE_EVAL来跟踪执行过程,参见后续章节。

  1. 求值器多实例
    AviatorEvaluator是一个全局静态实例,但是很多场景下,你可能想为不同的场景提供一个不同的求值器实例,包括不同的选项配置和自定义函数列表等,那么从 4.0.0开始, Aviator提供了多实例的求值器支持:
val instance = AviatorEvaluator.newInstance
//接下来使用 instance,几乎跟 AviatorEvaluator 没有不同,只是换成了实例方法
  1. 使用变量
    下面的例子演示了怎么向表达式传入变量值, 表达式中的world是一个变量, 默认为null, 通过传入Map<String,Object>的变量绑定环境, 将world设置为“world”。 env 的key是变量名, value是变量的值。
val world = "world"
val env = new util.HashMap[String,Object]()
env.put("world",world)
val result =AviatorEvaluator.execute(" 'hello ' + world ",env)
println(result)        //  hello world

'hello ‘是一个Aviator的String, Aviator的String是任何用单引号或者双引号括起来的字符序列, String可以比较大小(基于unicode顺序), 可以参与正则匹配, 可以与任何对象相加, 任何对象与String相加结果为String。 String中也可以有转义字符,如\n、\、’ 等。

AviatorEvaluator.execute(" 'a\"b' ")                  // 字符串 a"b
AviatorEvaluator.execute(" \"a\'b\" ")                // 字符串 a'b
AviatorEvaluator.execute(" 'hello ' + 3 ")              // 字符串 hello 3
AviatorEvaluator.execute(" 'hello '+ unknow ")         // 字符串 hello null
  1. exec 方法
    Aviator 2.2 开始新增加一个exec方法, 可以更方便地传入变量并执行, 而不需要构造env这个map了:
val value = "world"
AviatorEvaluator.exec("'hello' + value",value)        //  hello world
  1. 调用函数
    Aviator 支持函数调用, 函数调用的风格类似 lua, 下面的例子获取字符串的长度:
AviatorEvaluator.execute("string.length('hello')") 

string.length(‘hello’)是一个函数调用, string.length是一个函数, 'hello’是调用的参数。
再用string.substring来截取字符串:

AviatorEvaluator.execute("string.contains(\"test\", string.substring('hello', 1, 2))") // true

通过string.substring(‘hello’, 1, 2)获取字符串’e’, 然后通过函数string.contains判断e是否在’test’中。可以看到, 函数可以嵌套调用。

  1. 自定义函数
    Aviator除了内置的函数之外,还允许用户自定义函数,只要实现com.googlecode.aviator.runtime.type.AviatorFunction接口, 并注册到AviatorEvaluator即可使用. AviatorFunction接口十分庞大, 通常来说你并不需要实现所有的方法, 只要根据你的方法的参数个数, 继承AbstractFunction类并override相应方法即可。

这篇关于Aviator 一种表达式求值引擎的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/545443

相关文章

SpringBoot @Scheduled Cron表达式使用方式

《SpringBoot@ScheduledCron表达式使用方式》:本文主要介绍SpringBoot@ScheduledCron表达式使用方式,具有很好的参考价值,希望对大家有所帮助,如有... 目录Cron 表达式详解1. 表达式格式‌2. 特殊字符解析3. 常用示例‌4. 重点规则5. 动态与复杂场景‌

Spring Boot 集成 Quartz 使用Cron 表达式实现定时任务

《SpringBoot集成Quartz使用Cron表达式实现定时任务》本文介绍了如何在SpringBoot项目中集成Quartz并使用Cron表达式进行任务调度,通过添加Quartz依赖、创... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启

Spring Boot中定时任务Cron表达式的终极指南最佳实践记录

《SpringBoot中定时任务Cron表达式的终极指南最佳实践记录》本文详细介绍了SpringBoot中定时任务的实现方法,特别是Cron表达式的使用技巧和高级用法,从基础语法到复杂场景,从快速启... 目录一、Cron表达式基础1.1 Cron表达式结构1.2 核心语法规则二、Spring Boot中定

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名