非全自研可视化表达引擎-RuleLinK
说在前面
工作中经常会遇到这样的场景:
帮忙把小贝拉门店 商品金额在5w以内,产康订单最多95折。
帮忙把圣贝拉门店 开业时间在6个月内,折扣低于7折要发起审批
帮忙把宁波太平洋店设置独立合同模板
帮忙把节假日成本变成1000
...
有些三五月变一次,有些一月变一次,有些一周变几次,每次修改都是去巴拉代码,不胜其烦。
系统中的规则分散在各各PRD,有些人脑袋里也存了一份,但是随着人员的迭代,需求的迭代,最新永远散落在各初的代码中。这会带来诸多问题:
学习成本高
维护成本高
开发成本高
测试成本高
于是有了创建一个规则的管理与运营平台,以及支撑规则的解释与执行的框架的想法。用以消除样板式代码,解放生产力,让规则的变化变得的简单。
RuleLink的定位
RuleLink是一款可视化表达式引擎。致力于解决业务开发过程中,规则变化成本高, 规则管理分散,维护成本高,学习成本高,大量样板式代码等一系列的问题。
RuleLink名称的由来
用规则连接业务逻辑,让研发专注业务逻辑,让规则的配置变得的简单。
RuleLink 是基于 Aviatorscript 实现 规则的解析,基于开源项目 "rule-engine-builder-ui"实现表达式生成与渲染。(我只是代码搬运工,所以取名非全自研)
基于当下我们的业务规则量,RuleLink并未使用性能更好的 Rete算法,而是使用了传统的模式匹配。
为什么要建RuleLink
除了前面介绍的之外,另一个原因则是想弥补一下上一份的工作中的一点点小遗憾。
可视化表达式引擎的建设有两个难点:
表达式的解释与执行
表达式的生成与解析
第1点相对简单,于是在1月份时,捣鼓了一些基础代码,做了一些尝试,当时还因为部署Drools 的workbench 搞得停服20分钟,拿了人生第一C绩效。
到4月份接到这样一个需求,某业务线不同订单订单需要接不同的聚合支付账号。因为原来就换过一次了,为了支持快速切换,我们开始在Q1的代码基础做了一些调整,开始有了RuleLink的雏形。后来又陆续接入了一些场景:
新业务支付支持不同主体
订单折扣配置
...
更多的场景的接入,让可视化配置的需求变得比较必要。于是开始正式着手构建RuleLink,解决这一类的问题。
整体结构
目前主要使用Aviatorscript 解析表达式,并支持SpE
这是从其他复制的一张图(忘记出处),因为和自己的场景几乎一模一样,就直接引用了。
存储模型
Rule_Scene 规则场景
定义场景,目前场景是固定,现在只支持支付,未来有新场景再加入
RuleFactObj 事实对象
RuleFactObjfield 事实对象字段
定义场景下的事实字段,主要用于将来前端可可视化操作。
RuleBase 规则库
定义规则,目前只支持表达式(未来考虑支持 特定脚本,比如groovy),目前只是定义规则命中返回 简单或者复杂数据类型,未来可以考虑执行某个运行(action)。
日期格式处理
日期格式原来的实现是SpEL的方式,这会引发一些问题,所以修改了其源码并重新编译生成支持Aviatorscript 支持的自定义函数方式
1 /**
2 * @Author: jijunjian
3 * @CreateTime: 2023-08-25 17:52
4 * @Description: 自定义函数初始化
5 */
6 @Component
7 @Slf4j
8 public class CustomFunctionInitializer implements ApplicationContextAware {
9
10 @Override
11 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
12 log.info("初始化自定义函数");
13 AviatorEvaluator.addFunction(new StringToTimestamp());
14 log.info("初始化自定义函数完成");
15 }
16
17 /**
18 * 自定义函数
19 * 时间字符串转时间戳
20 */
21 class StringToTimestamp extends AbstractFunction {
22 @Override
23 public AviatorObject call(Map<String, Object> env,
24 AviatorObject arg1, AviatorObject arg2) {
25 String timeString = FunctionUtils.getStringValue(arg1, env);
26 String format = FunctionUtils.getStringValue(arg2, env);
27 // 10位时间戳
28 long timeStamp = DateUtil.parse(timeString, format).getTime()/1000;
29 return AviatorLong.valueOf(timeStamp);
30 }
31
32 @Override
33 public String getName() {
34 return "string_to_timestamp";
35 }
36 }
37 }
表达式解析
使用Aviatorscript解析比较简单,直接上代码
1 /**
2 * 根据表达式执行
3 * @author: jijunjian
4 * @param factObj
5 * @param expression
6 * @return
7 */
8 @Override
9 public boolean fire(Object factObj, String expression){
10 Map<String,Object> fact = new HashMap<>();
11 fact.put("data",factObj);
12 // 对于有字符串的表达式,需要先编译(并缓存,减少生成的临时类)
13 Expression compiledExpression = AviatorEvaluator.compile(expression,true);
14 log.info("开始执行表达式:{}, fact:{}", expression, JSONUtil.toJsonStr(factObj));
15 Boolean flag = (Boolean) compiledExpression.execute(fact);
16 log.info("开始执行表达式:{}, fact:{}, result:{}", expression, JSONUtil.toJsonStr(factObj), flag);
17
18 return flag;
19 }
20 点击并拖拽以移动
交互界面
写在最后
虽然现在的版本距离真正让运营同学能直接用起来了,可能还有一定的距离。比如各种枚举支持选项,门店等动态数据支持选项,返回结果支持动态渲染和选择等都还不不具备。但是1.0版本比原来硬编码,甚至nacos配置已经强上许多了。毕竟还是和两个小伙伴挤压业余时间开发,实为不易,于是来一次简单的聚餐,于是我们预定了未来每次大的版本升级,都来一次
上一份工作时,就有要构建一个简单易用的规则引擎,一直没能实现,有些许遗憾,今天算是给补上了。
微信:jijunjian
成为一名优秀的程序员!
非全自研可视化表达引擎-RuleLinK的更多相关文章
- OSG 初始化为非全屏窗口
OSG默认的窗口时全屏的,调试的时候不方便. 在网上看到一段代码,可以非全屏显示 int _tmain(int argc, _TCHAR* argv[]){ osgViewer::Viewer vie ...
- GIS案例学习笔记-三维生成和可视化表达
GIS案例学习笔记-三维生成和可视化表达 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:针对栅格或者矢量数值型数据,进行三维可视化表达 操作时间:15分钟 案 ...
- 表格中的checkbox复选框 全选非全选 公共方法 及提交选中结果
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 微信非全屏播放设置(仅Iphone)
由于微信X5内核强制视频全屏,用X5自带内核播放,一般内嵌视频打开播放就会被全屏. ihpone里面可以通过设置 x-webkit-airplay="true" webkit-pl ...
- 让DuiLib CheckBox支持全选、全不选、非全选三种状态
原文 https://blog.csdn.net/EveyX/article/details/38433783 DuiLib官方库中的Checkbox只有Checked和Uncheck两种状态,但我们 ...
- IOS(苹果手机)使用video播放HLS流,实现在内部播放及全屏播放(即非全屏和全屏播放)。
需求: 实现PC及移动端播放HLS流,并且可以自动播放,在页面内部播放及全屏播放功能. 初步:PC及安卓机使用hls.js实现hls流自动播放及全屏非全屏播放 首先使用了hls.js插件,可以实现在P ...
- Python全栈 MySQL 数据库 (引擎、事物、pymysql模块、orm)
ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 为了梦想为了信仰 开局一张图 存储引擎(处理表的处理器) 基本操作: ...
- C++多小球非对心弹性碰撞(HGE引擎)
程序是一个月前完成的,之前一直没正儿八经的来整理下这个程序,感觉比较简单,不过即使简单的东西也要跟大家分享下. 源码下载:http://download.csdn.net/detail/y851716 ...
- 阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算
日前,阿里巴巴正式对外发布了分布式科学计算引擎 Mars 的开源代码地址,开发者们可以在pypi上自主下载安装,或在Github上获取源代码并参与开发. 此前,早在2018年9月的杭州云栖大会上,阿里 ...
- PLDroidPlayer 是七牛推出的一款免费的适用于 Android 平台的播放器 SDK,采用全自研的跨平台播放内核,拥有丰富的功能和优异的性能,可高度定制化和二次开发。 https://developer.qiniu.com/pili/sdk/…
PLDroidPlayer PLDroidPlayer 是一个适用于 Android 平台的音视频播放器 SDK,可高度定制化和二次开发,为 Android 开发者提供了简单.快捷的接口,帮助开发者在 ...
随机推荐
- pupstudy的使用
打开环境 点击管理--打开根目录 把靶场放在www文件夹里 网页打开127.0.0.1/靶场文件名即可
- Serverless冷扩机器在压测中被击穿问题
一.现象回顾 在今天ForceBot全链路压测中,有位同事负责的服务做Serverless扩容(负载达到50%之后自动扩容并上线接入流量)中,发现新扩容的机器被击穿,监控如下(关注2:40-3:15时 ...
- 安装Visio 2016与原本的office冲突的最终解决方案
一. 下载office visio 2016 二. 开始安装 但是提示卸载原本的office 三. 网上找寻答案 于是按照这篇文章https://jingyan.baidu.com/article/1 ...
- Redash 可视化BI系统部署安装及简单使用
这篇文章主要为介绍一下Redash的使用和安装 概览 Redash 主要使用的语言为 Python 和 TypeScript 这个安装主要是基于Docker 来安装的,官网教程基本没有不是基于Dock ...
- 在C++中,传值还是传引用?
情况一:需要修改原对象 需要修改原对象的情况,必须要传引用.这种情况没什么要说的. 情况二:不需要修改原对象 对于内置类型(整数.浮点数.字符类型等),传值效率更高.主要有三点原因: 内存开销更小.由 ...
- UART-UART非常见波特率调试应用笔记
UART非常见波特率调试 应用笔记 串口通信中的波特率选择,对于确保可靠的数据传输至关重要.波特率是衡量单位时间内传输的比特数,常见的波特率包括300.1200.2400.9600.115200等.不 ...
- 图扑虚拟现实 VR 智慧办公室可视化
前言 "虚拟现实"是来自英文"Virtual Reality",简称 VR 技术,其是通过利用计算机仿真系统模拟外界环境,主要模拟对象有环境.技能.传感设备和感 ...
- 基于 python3+nginx 的 Jupyter Notebook 服务端 ssl 访问
引言 Jupyter Notebook(原名 ipython)可是科学计算界的必备工具,友好的界面,方便的交互,支持 Markdown,集中的极客们想要的一切特点,同时又制作的如此优雅和精美,真是难能 ...
- JavaWeb编程面试题——Spring Web MVC
引言 面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待.不以刷题进大厂为目的,而是以学习为目的.这里的知识点会持续更新,目录也会随时进行调整. 关注公众号:编 ...
- 20230611 再次升级SSD
家里常用电脑的硬盘又显得捉襟见肘,老规矩,升级SSD.幸亏几年前摸索的方法记录下来了,翻出以前的博客复习一下.为了保险起见,也重新在网上搜了一下,看是不是有新的更方便的方法,答案是没有,只是搜出很多推 ...