借老系统重构机会我写了个groovy规则引擎

公司老系统的重构计划早就有了,为了对Java硬编码的各种校验规则进行重构,特地参考了相关技术,最终选择了groovy进行了系统的学习,并编写了一个即插即用的轻量级规则引擎。

文章目录

    • 项目背景
    • 技术选型
    • groovy的性能
    • groovy脚本执行线程安全问题
    • 统一Java运行环境
    • dsl风格的规则声明
    • 弱类型的便利
    • 校验规则的维护
    • 基于事实推断的规则引擎实现

项目背景

笔者上班负责的是一个很老的某业务平台的申报系统。并发量随不高,但是申报分了很多的阶段,且每个阶段的申报项比较多,表单的字段也很多,校验规则也比较杂。项目前期有多个团队先后负责,代码风格不同,且业务规则的校验实现都是堆砌代码的方式,导致后期的代码维护比较麻烦。一个类文件通常是5千行代码以上,一个校验方法也至少几百行。

因为业务操作主要是数据的保存和申报,而校验的代码占到很大的比例,为此笔者的重构,很自然就想到把各种杂七杂八的校验代码给抽取出来,以规则脚本的形式进行更好的维护。

技术选型

抽取校验规则的技术选型,考虑了基于rete算法的drools、基于mveleasyRule以及jvm体系的groovy。因为只是把系统中的校验规则抽取出来,做成脚本的形式维护,传统的规则引擎也基本用不上,因为它们更多的使用场景是基于多实体的事实对象的分析、推断,且比较重量级,且有一定的学习成本。而groovy本身就是一门动态的脚本语言,很轻量级,可以在java环境无缝衔接的调用,语法非常的简洁易学,它的dsl特性还能编写出可读性更高的脚本声明形式。

groovy的性能

groovy非常的轻量级,编译速度很快,新版本对编译的内容做了缓存,而且gc方面也做了优化。笔者在这方面做了一些实验:通过spring boot的定时任务每隔一秒钟用30个线程同时跑groovy规则脚本,并对应用的jvm参数-XX:MetaspaceSize-XX:MaxMetaspaceSize都做了限制。用groovy老版本和新版本做了下对比,发现老版本执行很快就oom了:

在这里插入图片描述

而新版本稳定发挥,执行的性能用visualVM监控了下:

在这里插入图片描述

笔者还测试了下规则执行的耗时,第一次访问时需要耗时几百毫秒,后续就很快了,说明重复执行一个规则脚本,会缓存一些编译的类,提高性能:

在这里插入图片描述

groovy脚本执行线程安全问题

groovy脚本在java环境中的执行有多种方式,具体可参考这篇技术博客Integrating Groovy into Java Applications。我们采用GroovyShell的方式来执行规则脚本,因为规则是设计为dsl声明方式,而不是类和方法的执行方式,用bingding作为执行的上下文。binding本身是线程不安全的,在多个请求线程用同一个GroovyShell实例执行时,binding上绑定的变量是共享的,为此在实现上需要进行线程同步处理。而我们的做法是每次都创建一个新的GroovyShell来避免这个问题,这种方式没有性能问题,因为groovy本身就有对编译脚本相应的类缓存机制,且gc方面做了优化。

统一Java运行环境

在植入groovy脚本代码到当前的java系统时,可以设置加载groovy的类加载器为当前java系统的类加载器,这样就可以直接使用当前环境中的类和类库了。比如可以在groovy脚本中直接用获取spring bean的工具类:

在这里插入图片描述

而外部需要传进来参与规则执行的对象可以通过设置为binding的变量。

groovy脚本中抛出异常,和在java系统中抛出的异常类型信息一样,不会被包装,方便系统原有的异常处理机制统一处理:

在这里插入图片描述

dsl风格的规则声明

借助于groovy闭包和binding可以很轻松的实现dsl风格的声明:

在这里插入图片描述

这里的condition以及逻辑运算闭包还可以进一步优化成,不满足逻辑条件就不再执行,比如上面截图中的第一个condition满足条件,则后续的闭包不再解析执行,都可以自行控制实现。

弱类型的便利

原先在java代码中编写的各种校验规则,需要严格的静态类型检查还需要避免在运行时的空指针问题,而groovy天生就有类似于javascript的弱类型特性,且变量属性的访问,也不会有空指针问题,比如Integer类型的变量为null,使用<操作符;或者值为null的字符串变量调用equals

在弱语言中有一个特别需要注意的问题,变量可能存在全局污染,我们只要遵循这样的原则:在一个groovy脚本的头部声明变量时一定加上def,因为不用类型声明的变量会作为全局变量,可以在shell工具运行的多个脚本之间传递使用,因此要避免这一点。以下是笔者的练习:

在这里插入图片描述

校验规则的维护

对于简单的参数校验:非空、长度、正则等可以编写统一的groovy函数或者闭包,这样字段校验的脚本会变得非常简单,而对于复杂的关联性的校验只需要用java或者groovy脚本,在我们定义的condition中自由发挥即可。

在这里插入图片描述
运行结果:
在这里插入图片描述

另外通过这样的方式可以把规则成块的组织起来,包含了规则头部的声明块(变量的声明和初始化)、各个规则rule闭包声明的规则执行块。有了这样的结构后,可以把规则的定义从文件搬到数据库中,然后再通过web端的编辑权限进行修改维护(用支持groovy语法高亮的web编辑器),这样就可以做到不重启服务器的情况下,来动态更新业务规则,非常的省心。

基于事实推断的规则引擎实现

基于groovy强大的闭包语法特性,我们可以很轻松的实现笛卡尔积匹配方式的小型规则引擎,比如:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI科学家:自动化科研的未来之路

随着人工智能&#xff08;AI&#xff09;技术的不断进步&#xff0c;AI已经在众多领域中展现了强大的潜力&#xff0c;尤其是在科研方面的应用正在引起广泛关注。最近&#xff0c;Sakana AI与牛津大学和不列颠哥伦比亚大学联合推出了一款被称为“AI科学家”的自动化科研工具&am…

提升LLM结果:何时使用知识图谱RAG

通过知识图谱增强 RAG 可以帮助检索&#xff0c;使系统能够更深入地挖掘数据集以提供详细的响应。 有时&#xff0c;检索增强生成 (RAG) 系统无法深入文档集以找到所需的答案。我们可能会得到泛泛的或肤浅的回复&#xff0c;或者我们可能会得到回复&#xff0c;其中 RAG 系统检…

IA——网络操作设备VRP简介

一&#xff0c;VRP简介 二&#xff0c;网络设备的管理 &#xff08;1&#xff09;console口&#xff1a; &#xff08;2&#xff09;talnet: &#xff08;3&#xff09;SSH: 安全的远程登陆 &#xff08;4&#xff09;通过WEB页面登录&#xff1a; 三&#xff0c;命令行常见…

周星驰《大话大话西游》开机,“悟空热”席卷短剧市场?

继《黑神话&#xff1a;悟空》掀起文娱行业的“悟空热”之后&#xff0c;对市场变化最为敏感的短剧行业也赶上了这波热潮。 9月2日&#xff0c;由丽泽影业承制、周星驰九五二七剧场的第二部短剧《大话大话西游》正式开机。 从剧名就不难看出&#xff0c;《大话大话西游》是周星…

MySQL数据库安装(详细)—>Mariadb的安装(day21)

该网盘链接有效期为7天&#xff0c;有需要评论区扣我&#xff1a; 通过网盘分享的文件&#xff1a;mariadb-10.3.7-winx64.msi 链接: https://pan.baidu.com/s/1-r_w3NuP8amhIEedmTkWsQ?pwd2ua7 提取码: 2ua7 1 双击打开安装软件 本次安装的是mariaDB&#xff0c;双击打开mar…

OPC DA

默认端口号: TCP 135 参考https://wenku.baidu.com/view/8f2b18a229f90242a8956bec0975f46527d3a7e4.html?_wkts_1725526157944&bdQuery%E6%9F%A5%E7%9C%8B%E8%A5%BF%E9%97%A8%E5%AD%90opcDA%E7%AB%AF%E5%8F%A3%E5%8F%B7 OPC DA ,OPC UA简介https://www.cnblogs.com/mi…

Vue3 + Ts + Vite项目 websoket封装使用

文章目录 一、安装二、封装三、请求地址配置3.1 将接口地址放到 public3.2 引入 ipconfig.js 文件3.3 全局类型声明 四、页面使用4.1 引用4.2 注册 五、说明 一、安装 npm npm install websocket --save-devpnpm pnpm install websocket --save-dev二、封装 在 /src/utils …

类的加载过程与初始化小记

//部分内容来自“狂神说java” 代码验证 解释 1.加载类的信息&#xff0c;加载到内存中&#xff0c;如例子&#xff0c;将Test05和A类的信息加载到方法区&#xff0c; 2.加载完成后&#xff0c;立马生成一个class对象&#xff0c;如例 java.lang.class对象代表Test05类..., 3…

软件测试-Selenium+python自动化测试

目录 会用到谷歌浏览器Chrome测试,需要下载一个Chromedriver(Chrome for Testing availability)对应自己的浏览器版本号选择。 一、元素定位 对html网页中的元素进行定位,同时进行部分操作。 1.1一个简单的模板 from selenium import webdriver from selenium.webdrive…

Elastic Stack-ES集群常用的API

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 学习B站博主教程笔记&#xff1a; 最新版适合自学的ElasticStack全套视频&#xff08;Elk零基础入门到精通教程&#xff09;Linux运维必备—Elastic…

Origin2024中如何添加误差带?直观查看数据的变化范围

误差线是通常用于统计或科学绘图中&#xff0c;本期给大家分享Origin中绘制带填充区的误差带图&#xff0c;可以直观显示数据的变化范围&#xff0c;填充区域也可以增加视觉效果和美观性 操作步骤&#xff1a; 1、打开Origin2024软件&#xff0c;然后在Book1中输入如下示例数…

街机 SNK NeoGeo 中英文名字与驱动对照表

Part.I 简介 本文列举了街机 NeoGeo 中游戏的中英文名字与其驱动的对照&#xff0c;以帮助诸位更快地找到自己想玩的游戏。 注意&#xff1a;汉化版的街机模拟器 Kawaks 中游戏的中文名字是根据英文直译的&#xff0c;并不是习惯性的中文叫法。比如『三国志』英文名为『Warrio…

深度学习5从0到1理解RNN(包括LTSM,GRU等):内容丰富(上)

循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09; 是一种经典的深度学习网络结构&#xff0c;具有广泛的应用。其中&#xff0c;槽填充&#xff08;Slot Filling&#xff09;&#xff08;即识别自然语言中的特定信息&#xff09; 是其中一个应用场景&#x…

OpenSCAD 基础教程

OpenSCAD 基础教程 文章目录 OpenSCAD 基础教程1. 引言2. 安装与设置3. OpenSCAD 基本概念与语法3.1 基础形状3.2 变换操作3.4 布尔运算3.4 控制流3.5 特殊功能 4. 实践案例&#xff1a;创建一个简单的机械部件5. 高级技巧6. 导出与3D打印7. 常见问题与解决方案8. 结语 1. 引言…

虚拟机的安装-详细教程

目录 新建虚拟机 选择典型 安装操作系统 选择CentOS7 64位版本 虚拟机存放位置 磁盘容量 完成 编辑虚拟机 修改内存大小 设置处理器个数 选择镜像 开启虚拟机 进入界面&#xff0c;回车 选择语言 安装类型 磁盘分区 开启网络 设置密码和用户 重启 接受许可…

python进阶篇-day07-进程与线程

day06进程与线程 一. 进程 每个软件都可以看作是一个进程(数据隔离) 软件内的多个任务可以看作是多个线程(数据共享) 单核CPU: 宏观并行, 微观并发 真正的并行必须有多核CPU 多任务介绍 概述 多任务指的是, 多个任务"同时"执行 目的 节约资源, 充分利用CPU资源, …

unreal engine 5.4.4 runtime 使用PCG

Unreal PCG Runtime runtime环境下控制PCG PCG Graph 这里简单的在landscape上Spawn Static Mesh 和 Spawn Actor GraphSetting 自定义的参数&#xff0c;方便修改 场景 这里新建了一个蓝图Actor PCG_Ctrl, 用来runtime的时候控制PCG生成 Construct 获取场景中的PCGVolum…

开源还是封闭?人工智能的两难选择

这篇文章于 2024 年 7 月 29 日首次出现在 The New Stack 上。人工智能正处于软件行业的完美风暴中&#xff0c;现在马克扎克伯格 &#xff08;Mark Zuckerberg&#xff09; 正在呼吁开源 AI。 关于如何控制 AI 的三个强大观点正在发生碰撞&#xff1a; 1 . 所有 AI 都应该是开…

易保全出席人工智能应用场景高峰论坛,发布AI-数据资产管理平台2.0应用成果

2024年9月5日&#xff0c;由上海合作组织国家多功能经贸平台、重庆市科技发展基金会指导&#xff0c;重庆市渝中区商务委员会等相关部门主办、华智未来(重庆)科技有限公司承办&#xff0c;重庆民营经济国际合作商会协办的“智驭未来创想无界人工智能应用场景高峰论坛暨成果发布…

区块链-P2P(八)

前言 P2P网络&#xff08;Peer-to-Peer Network&#xff09;是一种点对点的网络结构&#xff0c;它没有中心化的服务器或者管理者&#xff0c;所有节点都是平等的。在P2P网络中&#xff0c;每个节点都可以既是客户端也是服务端&#xff0c;这种网络结构的优点是去中心化、可扩展…