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

相关文章

使用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提供个模板形参的名

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变