分享好友 最新动态首页 最新动态分类 切换频道
AviatorScript
2024-12-27 03:58


规则引擎由推理引擎发展而来是一种嵌入在应用程序中的组件实现了将业务决策从应用程序代码中分离出来并使用预定义的语义模块编写业务决策

规则引擎具体执行可以分为接受数据输入解释业务规则根据业务规则做出业务决策几个过程。

在线申请信用卡的业务场景,用户需要录入个人信息,如下图所示

通过上图可以看到,用户录入的个人信息包括姓名、性别、年龄、学历、电话、月收入、是否有房、是否有车、是否有信用卡等。录入完成后点击申请按钮提交即可。

用户提交申请后,需要在系统的服务端进行用户信息合法性检查(是否有资格申请信用卡),只有通过合法性检查的用户才可以成功申请到信用卡(注意:不同用户有可能申请到的信用卡额度不同)。

检查用户信息合法性的规则如下

规则编号名称描述1检查学历与薪水1如果申请人既没房也没车,同时学历为大专以下,并且月薪少于5000,那么不通过2检查学历与薪水2如果申请人既没房也没车,同时学历为大专或本科,并且月薪少于3000,那么不通过3检查学历与薪水3如果申请人既没房也没车,同时学历为本科以上,并且月薪少于2000,同时之前没有信用卡的,那么不通过4检查申请人已有的信用卡数量如果申请人现有的信用卡数量大于10,那么不通过

用户信息合法性检查通过后,还需要根据如下信用卡发放规则确定用户所办信用卡的额度

规则编号名称描述1规则1如果申请人有房有车,或者月收入在20000以上,那么发放的信用卡额度为150002规则2如果申请人没房没车,但月收入在10000~20000之间,那么发放的信用卡额度为60003规则3如果申请人没房没车,月收入在10000以下,那么发放的信用卡额度为30004规则4如果申请人有房没车或者没房但有车,月收入在10000以下,那么发放的信用卡额度为50005规则5如果申请人有房没车或者是没房但有车,月收入在10000~20000之间,那么发放的信用卡额度为8000

思考:如何实现上面的业务逻辑呢

我们最容易想到的就是使用分支判断(if else)来实现,例如通过如下代码来检查用户信息合法性:

 

如果用户信息合法性检查通过后,还需要通过如下代码确定用户所办信用卡的额度

 

通过上面的伪代码我们可以看到,我们的业务规则是通过Java代码的方式实现的。这种实现方式存在如下问题

  1. 硬编码实现业务规则难以维护

  2. 硬编码实现业务规则难以应对变化

  3. 业务规则发生变化需要修改代码,重启服务后才能生效

那么面对上面的业务场景,还有什么好的实现方式吗

答案是规则引擎。

规则引擎实现了将业务决策从应用程序代码中分离出来,接受数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。

上面的申请信用卡业务场景使用规则引擎后效果如下

业务系统运行过程中难免会发生业务规则变化的情形,有了规则引擎,业务规则部分采用的是规则引擎实现,这样在系统正常运行的情况就可以利用规则引擎对业务规则进行修改,从而实现业务规则的随需应便。

1、业务规则与系统代码分离,实现业务规则的集中管理

2、在不重启服务的情况下可随时对业务规则进行扩展和维护

3、可以动态修改业务规则,从而快速响应需求变更

4、规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则

5、减少了硬编码业务规则的成本和风险

6、使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单

开源的代表是Drools,商业的代表是VisualRules ,iLog。

Java 开源的规则引擎有:Drools、URule、Easy Rules。使用最为广泛 Drools。

通过类型对规则引擎进行简单分类,一般有以下3类

  • 通过界面配置的成熟规则引擎:这种规则引擎相对来说就比较重,但是因为功能全,也有部分业务会选择这个,比较出名的有:Drools、URule
  • 基于JVM脚本语言:这种其实不是一个成熟的规则引擎,应该算是规则引擎中的核心技术,因为Drools这种相对太重了,很多互联网公司会基于一些jvm的脚本语言,开发一个轻量级的规则引擎,比较出名的有:Groovy、AviatorScript、QLExpress。
  • 基于java代码的规则引擎:上面是基于jvm脚本语言去做的,会有一些语法学习的成本,所以就有基于java代码去做的规则引擎,比如通过一些注解实现抽象的方式去做到规则的扩展,比较出名的有: Easy Rules

Drools 是用 Java 语言编写的开放源码规则引擎,基于Apache协议,基于RETE算法,于2005年被JBoss收购。

特性

  • 简化系统架构,优化应用。
  • 提高系统的可维护性和维护成本。
  • 方便系统的整合。
  • 减少编写“硬代码”业务规则的成本和风险。

Drools发展到今天,其实已经是一整套解决方案了。

如果只是想要简单使用,那就是只用到Drools的核心BRE,引入几个Maven依赖,编写Java代码和规则文件即可。但是如果要编排很复杂的工程,甚至整个业务都重度依赖,需要产品、运营同学一起来指定规则,则需要用到BRMS整套解决方案了,包括Drools Expert(BRE)、Drools Workbench、DMN。

所以我们说Drools太重了,主要是在说

  • Drools相关的组件太多,需要逐个研究才知道是否需要
  • Drools逻辑复杂,不了解原理,一旦出现问题排查难度高
  • Drools需要编写规则文件,学习成本高

Drools 官网 : https://www.drools.org
Drools 中文网 : http://www.drools.org.cn
Drools GitHub : https://github.com/kiegroup/drools

URule是一款纯Java规则引擎,提供基于Apache协议开源版本和商业版本,它以RETE算法为基础,提供了向导式规则集、脚本式规则集、决策表、交叉决策表(PRO版提供)、决策树、评分卡及决策流共六种类型的规则定义方式,配合基于WEB的设计器,可快速实现规则的定义、维护与发布。

URule的优点

  • 向导式规则配置:可以通过web页面配置规则,不依赖开发人员即可配置规则
  • 决策表、决策树:提供更加友好的、直观的、支持复杂的规则配置
  • 快速测试:在页面可快速构建规则测试
  • 集成方便

缺点

  • 开源版本提供的功能有限,无高级功能

URule 官网 : http://www.bstek.com
URule GitHub: https://github.com/youseries/urule

Easy Rules 是一款 Java 规则引擎,它的诞生启发自有Martin Fowler 一篇名为 “Should I use a Rules Engine?” 文章。Easy Rules 提供了规则抽象来创建带有条件和操作的规则,以及运行一组规则来评估条件和执行操作的RulesEngine API。

Easy Rules是一个简单而强大的Java规则引擎,提供以下功能

  • 轻量级框架和易于学习的API
  • 基于POJO的开发与注解的编程模型
  • 定义抽象的业务规则并轻松应用它们
  • 支持从简单规则创建组合规则的能力
  • 支持使用表达式语言(如MVEL和SpEL)定义规则的能力

Easy Rules GitHub : https://github.com/j-easy/easy-rules

Groovy是动态语言,依靠反射方式动态执行表达式的求值,并且依靠JIT编译器,在执行次数够多以后,编译成本地字节码,因此性能非常的高,适应于反复执行的表达式,用Groovy脚本动态调整线上代码,无须发版。

Groovy编译器先将.groovy文件编译成.class文件,然后调用JVM执行*.class文件,可以在Java项目中集成Groovy并充分利用Groovy的动态功能

Groovy兼容几乎所有的java语法,开发者完全可以将Groovy当做Java来开发,甚至可以不使用Groovy的特有语法,仅仅通过引入Groovy并使用它的动态能力

Groovy可以直接调用项目中现有的Java类(通过import导入),通过构造函数构造对象并直接调用其方法并返回结果。

Groovy 官网 : http://www.groovy-lang.org
Groovy GitHub : https://github.com/groovy

Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢

Aviator的设计目标是轻量级和高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。

其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式编译成Java字节码,交给JVM去执行。

支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式?: ,并且支持操作符的优先级和括号强制优先级,具体请看后面的操作符列表。

Aviator的限制

没有if else、do while等语句,没有赋值语句,仅支持逻辑表达式、算术表达式、三元表达式和正则匹配。

不支持八进制数字字面量,仅支持十进制和十六进制数字字面量。

AviatorScript 文档 : https://www.yuque.com/boyan-avfmj/aviatorscript
AviatorScript GitHub : https://github.com/killme2008/aviatorscript

QLExpress从一开始就是从复杂的阿里电商业务系统出发,并且不断完善的脚本语言解析引擎框架,在不追求java语法的完整性的前提下(比如异常处理,foreach循环,lambda表达式,这些都是Groovy的强项,定制了很多普遍存在的业务需求解决方案(比如变量解析,spring打通,函数封装,操作符定制,宏替换,同时在高性能、高并发、线程安全等方面也下足了功夫,久经考验。

QLExpress GitHub : https://github.com/alibaba/QLExpress
参考 : https://developer.aliyun.com/article/621206

可分为3类

  • 低配版:没有配置界面,靠业务人员编写引擎规则DSL,一般存储在数据库或者文件中,这种没有彻底解放业务人员和开发人员的耦合,但是加快了业务代码的上线速度,以及很容易就能进行规则变更。
  • 进阶版:这个一般是某种特定的系统,我们针对这种系统设置一些有针对性的页面,比如下面是某风控系统的截图,风控系统的规则引擎是相对来说比较简单的,只需要判断某些参数是否符合某些条件即可,然后返回固定的值即可。
  • 完全版:在进阶版中规则引擎只是其中的一个部件,一般这种都很难复用于其他场景。但是一个完全版的规则引擎,追求的超高的通用性,下面是从一个商业的规则引擎中截图

可以看见提供了多种规则引擎的表达:比如决策集,决策表,决策树等等,适用于我们很多需要使用规则引擎的地方,下面展示了一下决策树的配置,这个就和我们上面风控的配置有点类似,只不过通用性更强。

AviatorScript 文档 : https://www.yuque.com/boyan-avfmj/aviatorscript
AviatorScript GitHub : https://github.com/killme2008/aviatorscript

1.1 原理和特点

Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟,这样就保证了它的性能超越绝大部分解释性的表达式引擎,测试也证明如此;其次,除了依赖 commons-beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K。同时, Aviator 内置的函数库非常“节制”,除了必须的字符串处理、数学函数和集合处理之外,类似文件 IO、网络等等你都是没法使用的,这样能保证运行期的安全,如果你需要这些高阶能力,可以通过开放的自定义函数来接入。因此总结它的特点是

 

1.2 Hello World

AviatorScript 是一门寄生在 JVM (Hosted on the JVM)上的语言。

1.2.1 AviatorScript 引擎

AviatorScript 编译和执行的入口是 AviatorEvaluatorInstance,该类的一个实例就是一个编译和执行的单元,这个单元我们称为一个 AviatorScript 引擎,你可以多个引擎,每个引擎可以设置不同的编译和运行选项。

AviatorEvaluator.getInstance() 返回一个全局共享的 AviatorScript 引擎。

1.2.2 编译脚本文件

首先,在你的 java 项目里引用下 AviatorScript 的依赖

 

接下来编写你的第一个 AviatorScript 脚本AviatorScript 脚本源码文件约定以 .av 作为文件后缀

 

连续的两个 # 号引入一行注释。这段代码非常简单,调用 println 函数,打印字符串 hello, AviatorScript! 。

其次,编写一个类来运行测试脚本

 

这段代码逻辑很简单

  1. 使用 AviatorEvaluatorInstance#compileScript 方法编译脚本到 Expression 对象
  2. 调用 Expression#execute() 方法执行

输出

 

AviatorEvaluatorInstance 有诸多方法,我们用 compileScript(path) 方法编译一个脚本文件,这个方法对文件路径查找按照下列顺序

  • path 指定的文件系统绝对或者相对路径
  • user.dir 项目的根目录开始的相对路径
  • classpath 下的绝对和相对路径

找到就尝试读取脚本并动态实时地编译成 JVM 字节码,最终的结果是一个 Expression 对象(为什么叫 Expression 而不是 Script ,这是历史遗留问题,因为 aviator 一开始只是一个表达式引擎)。所有的脚本最终编译的结果都是一个 Expression 对象,它经过

  • Lexer 文法分析
  • Parser 语法解析
  • 一趟优化:常量折叠、常量池化等简单优化。
  • 第二趟生成 JVM 字节码,并最终动态生成一个匿名 Class
  • 实例化 Class,最终的 Expression 对象。

每次调用 compileScript(path) 都生成一个新的匿名类和对象,因此如果频繁调用会占满 JVM 的 metaspace,可能导致 full gc 或者 OOM,因此还有一个方法 compileScript(path, cached) 可以通过第二个布尔值参数决定是否缓存该编译结果。

 
1.2.3 编译脚本文本

假设你的脚本存储在其他地方,比如数据库的文本字段,或者远程文件,获取后是一个 String 字符串对象,你可以通过 AviatorEvaluatorInstance#compile(script) 方法来编译,同样结果是一个 Expression 对象。事实上 compileScript 方法最终调用的也是 compile 方法。

 

AviatorEvaluator.compile 是 AviatorEvaluator.getInstance().compile 的等价方法。

运行结果同样是打印了 Hello, AviatorScript! 。注意,这里字符串 Hello, AviatorScript! 是用单引号括起来的,在 AviatorScript 中字符串可以是双引号括起来,也可以是单引号括起来,作为字面量表达就省去了转义的麻烦。

compile 方法默认不缓存编译结果,同样有缓存的重载版本方法 compile(final String expression, final boolean cached) ,如果第二个参数为 true 将以 script 文本为 key 来缓存编译结果,但是如果你的脚本特别长,用来做缓存 key 会占用比较多的内存,这时候你可以指定缓存 key ,只要调用 compile(final String cacheKey, final String expression, final boolean cached) 方法即可。

1.2.4 执行

编译产生的 Expression 对象,最终都是调用 execute() 方法执行,得到结果。但是 execute 方法还可以接受一个变量列表组成的 map,来注入执行的上下文,我们来一个例子

 

我们编译了一段脚本 a-(b-c) > 100 ,这是一个简单的数字计算和比较,最终返回一个布尔值。a, b, c 是三个变量,它们的值都是未知,没有在脚本里明确赋值,那么可以通过外部传参的方式,将这些变量的值注入进去,同时求得结果,比如例子是通过 Expression#newEnv 方法创建了一个 Map<String, Object 的上下文 map,将 a 设置为 100.3,将 b 设置为 45,将 c 设置为 -199.100,最终代入的执行过程如下

 

因此返回的 result 就是 false。

这是一个很典型的动态表达式求值的例子,通过复用 Expression 对象,结合不同的上下文 map,你可以对一个表达式反复求值。

1.3 关系

最新文章
这一抹红色,是从未忘却的纪念
它是飘落在地球上的一根红飘带是贵州旅游打卡的新地标它是什么?全国首个以长征为主题的全域行浸式数字科技体验馆“红飘带”项目9259如果奇迹有颜色那一定是中国红那,这样的红色你见过吗?它取自赤水河边的泥岩之色象征长征的艰辛历程和革
百度推广和安全联盟认证已被取消,现为百度信誉V认证
目前,在百度搜索框中输入某些关键词并搜索到一些自然网站排名时,把鼠标移动到百度推广蓝色V认证上面,发现没有显示百度推广身份认证和安全联盟认证字样,而是显示V已经通过百度信誉认证。由此看来,百度已经将百度推广认证和安全联盟认证
抖音信息流和内容热推的区别?抖音信息流价格分析软件
抖音广告投放策略比较:信息流和内容热推摘要:抖音作为当前流行的短视频平台,广告投放已经成为企业推广的重要手段。其中,信息流和内容热推是两种主要的广告投放策略。本文将从四个方面详细对比这两种策略的特点和应用场景,帮助企业更好
外贸SOHO建站报价——建个个人外贸网站多少钱
很多外贸SOHO和企业都需要建立外贸网站作为品牌推广的重要平台。因此,如果我们想知道建立一个外贸网站的价格,开发外贸网站Ueeshop可以跟大家一起看看都包含了哪一些内容。对于需要建立外贸网站的用户来说,他们可以看到很多不同的价格,
松鼠AI智能学习机:高效全科辅导新选择
松鼠AI智能学习机是一款高效全科辅导新选择,它结合了人工智能技术和教育知识体系,可以帮助学生自主学习、提高学习效率。松鼠AI智能学习机拥有多种学科的课程,包括语文、数学、英语、科学等,覆盖了小学到初中各年级的内容。学生可以根据
语音直播聊天系统开发(APP、公众号、小程序)
2015年01月15日潘锦霖系统开发,软件开发,APP开发,源码搭建,定制软件,社交电商,云电商,新媒体电商,O2O,F2C,B2C,B2B2C,F2B2C,C2B,B2C2N,S2B2C,微商城,App,手机网页,PC商城,小程序,微商管理系统,扫码红包,质量追溯,分销系统, 全返系统,分红系
用AI轻松生成超逼真美女写真,这款工具你一定要试!
在这个科技飞速发展的时代,AI生成技术的应用已经渗透到我们生活的各个角落。尤其是在摄影和艺术创作领域,AI工具带来了前所未有的便捷与可能性。想象一下,不用外出,只需要在你的手机或电脑屏幕前,就可以生成各类超逼真的美女写真,不再
魅族Lucky 08:性能强劲,拍照专业,千元机中的佼佼者
在当今智能手机市场,AI技术已成为各大品牌竞相追逐的焦点。魅族Lucky 08 AI手机,凭借其独特的AI功能和卓越的硬件配置,迅速成为市场上的热门话题。这款手机不仅在AI应用上有所创新,更在续航、屏幕显示和摄影等方面表现出色,为用户带来
精美PHP导航收录网站源码-QQ技术导航程序源码
划算本站会员的9大好处?1.发布的源码/资源,都已经经过本站/其他站长/用户大部分亲测可使用,质量极高!2.本站只发布合法内容,从不发布违法内容,服务器以续费5年,网站安全长久不跑路!3.本站整合了多个网站的永久高级会员,开通本站会
探讨数学与AI的奇妙碰撞:2024中国人工智能大会即将召开
即将于2024年12月13日至15日在北京举行的2024中国人工智能大会(CCAI 2024),将以“创新驱动智启新程”为主题,汇聚了数学与人工智能领域的重量级专家,其中包括丘成桐院士、戴琼海院士、林文伟教授等重量级嘉宾,他们将展开一场关于“AI
相关文章
推荐文章
发表评论
0评