规则引擎-Easy rule

规则引擎-Easy rule

最近有几个项目中都出现了根据XX条件执行XX方法的业务,在动手之前脑中总会下意识的发现如果按照常规的去写代码,无论使用何种设计模式,都会出现不同程度上的代码冗余或大量if-else判断。

甚至说判断XX条件的代码和执行XX方法的代码,非常容易出现上下级调用的关系;

在多的这些功能熟练之后,规则引擎可以完美的适配这种 根据XX条件执行XX方法 的业务;

什么是规则引擎

如其名,定义规则的执行引擎,是一套解决业务代码与执行其业务规则分离的解决方案或组件;

举个例子:有一个功能为,当用户输入A时,将用户的信息更新为B

如果按照常规代码来说,伪代码为:

public void update(String mess) {if(mess.equlas("A")){//更新}
}

如果使用规则引擎则变成:

public void rule(String mess){Rules rules = new Rules();rules.register(new RuleBuilder().when((facts -> facts.get("mess").equals("A"))).then(facts -> {System.out.println("更新B");}).build());RulesEngine rulesEngine = new DefaultRulesEngine();Facts facts = new Facts();facts.put("mess","A");rulesEngine.fire(rules,facts);
}

可以直观的感受到,怎么使用了规则引擎之后代码变多了而且变复杂了?

且慢,让我们认真缕一缕;

现在我们需要添加一个新逻辑,当用户输入B时,将信息更新为C;

在常规中,有两种选择:

  1. 继续往后叠If-else或者使用switch
  2. 使用策略模式,将输入的内容作为策略key;

在规则引擎中,有两种选择:

  1. 继续在.when()和.then()中堆叠
  2. 将.when()和.then()的实际动作抽离成策略方法,各做各的事。

或许还不够直观看出改变,那么我再添加一个前提,如果是 当用户输入???,其中n个条件,只需要满足其中之一,那么就执行更新动作;

在常规中,是不是只有两种办法:

  1. 数据库配置
  2. 写死一个map,进行判断

再规则引擎中,我只需要将从.when()中抽离出来的校验解析式进行通过配置即可,比方说使用Sql语句作为.when()方法中的结果;

规则为:SELECT * FROM xxx WHERE mess IN ('A','B','C','D','E')

构建的facts.put("mess",mess); 就可以在不动任何代码的前提下仅通过已经抽离的.when()中的表达式 规则 完成新规则-执行逻辑的拓展;

其结构组成为:

Easy-rule

在JAVA几大主流的规则引擎:

规则引擎优势缺点
DroolsDrools 支持复杂的规则和事件处理,具有强大的表达能力。
它提供了一个易于使用的 DSL (领域特定语言) 来表示规则,使得非技术人员也能够理解和维护规则。
学习曲线较陡,对于新手来说可能需要一定的时间来学习和掌握。
在处理大规模数据时性能可能不如其他规则引擎。
JBossRulesJBoss Rules 是 Drools 的早期版本,提供了类似的规则引擎功能。由于是 Drools 的早期版本,可能缺少一些新功能和改进。
Easy RulesEasy Rules 是一个轻量级的 Java 规则引擎,适用于简单的规则场景。
易于学习和使用,适合快速集成到项目中。
不适用于复杂规则场景,功能相对有限。
Camel KCamel K 是 Apache Camel 的 Kubernetes 版本,可以与 Kubernetes 环境集成。
具有强大的路由和转换功能,适用于复杂的集成场景。
相对于专门的规则引擎,可能在规则管理和表达能力上略显不足。

EasyRule适用于目前遇到的绝大多数的项目,且即使需要复杂的规则场景,也可以通过其余的表达式组件去构建自定义的规则表达式,比如前文案例中提到的Sql表达式;

简单的概括一下适用教程:

引入

<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>4.1.0</version>
</dependency>

使用

https://github.com/j-easy/easy-rules

这里不介绍使用注释的方式,推荐链式编程,代码更加直观清晰:

public void runle(){
Rules rules = new Rules();
rules.register(new RuleBuilder().when((facts -> return true;).then(facts -> {System.out.println("hellow");}).build());
RulesEngine rulesEngine = new DefaultRulesEngine();
Facts facts = new Facts();
rulesEngine.fire(rules,facts);
}

也可以使用文件的方式定义规则

name: "weather rule"
description: "if it rains then take an umbrella"
condition: "rain == true"
actions:- "System.out.println(\"It rains, take an umbrella!\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
Rule weatherRule = ruleFactory.createRule(new FileReader("weather-rule.yml"));

Facts 中则是放入在.when()判断时需要用到的需要,通过put,get方法key-value的形式存储;

增强

对于简单的规则业务来说,往往都是 X=X,则执行?的判断;因此简单的可以直接通过yaml文件配置死;

但是在需要稍微复杂判断的业务中,则需要开发者自行增强;

比方说我现在有多个规则,有两种情况一是需要当这些规则都成立的时候才执行更新,二是只要其中一个规则成立就执行:

我们可以自定义一个规则执行类:

public class AllEstablishRule {private List<Rule> rules;private Runnable runnable;public AllEstablishRule(List<Rule> rules, Runnable runnable) {this.rules = rules;this.runnable = runnable;}public boolean evaluate(Facts facts) {boolean ok = false;for (Rule rule : rules) {ok = rule.evaluate(facts);if (!ok) break;}return ok;}public void execute(Facts facts) {if (evaluate(facts)) {runnable.run();}}
}

使用为:

AllEstablishRule allEstablishRule = new AllEstablishRule(CollectionUtil.newArrayList(new RuleBuilder().when((facts -> facts.get("mess").equals("A"))).build(),new RuleBuilder().when((facts -> facts.get("mess").equals("B"))).build()),()->{System.out.println("更新");});Facts facts = new Facts();facts.put("mess","A");allEstablishRule.execute(facts);

再比如,当需要复杂判断时,我们可以对.when()的判断动作作手脚;

比方说上述提到的SQL表达式,就可以通过使用 com.alibaba.druid.sql 包下的类解析SQL,使一个查询语句中的条件

where name = '小红' AND age = 14 OR sex = '男'

这些拼接成一个代码逻辑中的 &|判断以及 = ,in 的判断。

总结

因为在使用Easy-rule的体验中还没遇到解决不了的问题,所以还没涉及过其余的规则引擎,相信未来终有机会接触到他们;

Easy-rule再git社区上的活跃为3年前,并且其余的规则引擎的社区活跃度也远没有我们常用的框架、工具的多,可以看出规则引擎在设计中以及是一种非常成熟的解决方案了。

版权声明:本站原创文章,于2024-04-08,乐云一发表
转载请注明:https://leyunone.com/java/easy-rule.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024中国大学计算机科学与技术专业排名(非常详细)零基础入门到精通,收藏这一篇就够了

今天 6 月 8 号&#xff0c;高考第二天&#xff0c;随着大部分地区的高考结束&#xff0c;接下来就是焦急的等待分数的公布&#xff0c;然后学生们就迎来人生中的一个重要时刻——选择大学和专业。 在众多专业中&#xff0c;计算机科学与技术一直是备受瞩目的热门选择&#xf…

【爬虫】使用Python爬取百度学术页面的标题、作者、摘要和关键词

目录 安装所需库编写爬虫代码解释运行脚本结果 在本文中&#xff0c;我将介绍如何使用Python编写一个网络爬虫&#xff0c;从百度学术页面提取研究论文的标题、作者、摘要和关键词。我们将使用 requests和 BeautifulSoup库来实现这一目标。 安装所需库 首先&#xff0c;确保…

uniapp引入uview无代码提示

前提安装正确&#xff1a; 无论是基于npm和Hbuilder X方式安装&#xff0c;一定要配置正确。 解决办法 以前在pages.json里面的写法&#xff1a; "easycom": {"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue" }但是现在hbuilderx要求规范ea…

驱动开发之 input 子系统

1.input 子系统介绍 input 就是输入的意思&#xff0c;input 子系统就是管理输入的子系统&#xff0c;和 pinctrl、gpio 子系统 一样&#xff0c;都是 Linux 内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等 等这些都属于输入设备&#xff0c;不同的输入…

Redis到底支不支持事务?

文章目录 一、概述二、使用1、正常执行&#xff1a;2、主动放弃事务3、全部回滚:4、部分支持事务:5、WATCH: 三、事务三阶段四、小结 redis是支持事务的&#xff0c;但是它与传统的关系型数据库中的事务是有所不同的 一、概述 概念: 可以一次执行多个命令&#xff0c;本质是一…

《解决方案架构师修炼之道》读书笔记

1. 水在前面 第一次看到“解决方案架构师”这个词&#xff0c;就把这本书借回家翻了。最近也在网上看点资料&#xff0c;对比起来发现还是出版物内容更完整和更有体系&#xff0c;而且看书真的能让人安静下来。。。 《解决方案架构师修炼之道》所罗伯死里瓦斯塔瓦&#xff0c;内…

每天五分钟深度学习pytorch:pytorch中的广播机制是什么?

本文重点 在pytorch中经常有张量和张量之间的运算,那么有一点需要注意,那就是维度要匹配,如果维度不匹配就有可能出现问题。如果维度不一致,此时也可以同时进行操作,此时就需要使用pytorch中的广播机制,本节课程就讲解pytorch中的广播机制。 广播机制示意图 如上就是py…

RK3568技术笔记之三 SAIL-RK3568开发板板卡功能测试

从这里开始&#xff0c;就是老生常谈系列之一&#xff1a;板卡功能测试。 放一张图镇一下帖 按照我自己顺手的方式&#xff0c;把这板子功能测一下。 先把开发板串口信息打印出来。 工具 功能 备注 电脑&#xff08;必备&#xff09; 提供使用终端软件环境 需要具备至少…

【ArcGIS微课1000例】0117:ArcGIS中如何将kml(kmz)文件转json(geojson)?

文章目录 一、kml获取方式二、kml转图层三、图层转json一、kml获取方式 kml文件是一种很常用的数据格式,可以从谷歌地球(googleearth)获取某一个地区的kml范围文件,如青海湖(做好的kml文件可以从配套实验数据包0117.rar中获取)。 二、kml转图层 打开【KML转图层】工具,…

2 程序的灵魂—算法-2.4 怎样表示一个算法-2.4.2 用流程图表示算法

流程图表示算法&#xff0c;直观形象&#xff0c;易于理解。 【例 2.6】将例 2.1 求 5!的算用流程图表示。 【例 2.7】将例 2.2 的算用流程图表示。 【例 2.8】将例 2.3 判定闰年的算用流程图表示。

问题:功夫菜产品的成本由哪几方面构成() #经验分享#其他

问题&#xff1a;功夫菜产品的成本由哪几方面构成&#xff08;&#xff09; A&#xff0e;材料成本&#xff08;标准投料2%损耗&#xff09;包材成本直接人工费固定加工费 B&#xff0e;&#xff08;材料成本包材成本&#xff09;*&#xff08;1加价率&#xff09; C&#x…

Polar Web 【简单】- 被黑掉的站

Polar Web 【简单】- 被黑掉的站 Contents Polar Web 【简单】- 被黑掉的站思路EXP运行&总结 思路 如题目所述&#xff0c;这是一个被黑掉的站点&#xff0c;由此不禁要了解该黑客发现了哪些可以入手的路径&#xff0c;或是留下了什么样的文件供持续访问。 目录扫描该站点发…

【C++修行之道】类和对象(二)类的6个默认成员函数、构造函数、析构函数

目录 一、类的6个默认成员函数 二、构造函数 2.1 概念 2.2 特性 2.2.5 自动生成默认构造函数 不进行显示定义的隐患&#xff1a; 2.2.6 自动生成的构造函数意义何在&#xff1f; 两个栈实现一个队列 2.2.7 无参的构造函数和全缺省的构造函数都称为默认构造函数&#x…

计算机组成原理(一)

冯诺依曼机器的特征&#xff1a; 指令和数据以同等的地位存储在存储器当中指令和数据都是二进制指令和数据都是保存在存储器当中的 存储字 每个存储单元中的数据&#xff0c;称为存储字 存储字长 存储单元能够存储的二进制数据的长度 在一个8位系统中&#xff0c;字长是…

Java——IO流(一)-(1/8):File、IO流概述、File文件对象的创建(介绍、实例演示)

目录 File IO流概述 File文件对象的创建 介绍 实例演示 File 存储数据的方案 变量 double money 9999.5 数组 int[] age new int[100];对象 Student s new Student()集合 List<Student> students new ArrayList<>()…

[office] Excel教学:Excel通配符怎么用? #其他#职场发展

Excel教学&#xff1a;Excel通配符怎么用&#xff1f; 尽管Excel使用了很多年&#xff0c;但很多人都还是忽略了Excel通配符的存在&#xff0c;不知道通配符是什么&#xff0c;不知道如何使用它。今天我就完整地介绍一下通配符&#xff0c;让你彻底地认识通配符。 关于通配符…

递归(全排列andN皇后)

全排列 分治与递归 递归是实现分治的一种方法 思想思路 题目&#xff1a; 全排列i 我这样直接输出会多输出一个空行&#xff08;最后一个\n&#xff09; #include<stdio.h>using namespace std; const int maxn10; int an[maxn]; int n; bool hash[maxn]{0}; int c0…

微服务架构-可见可观测与量化分析体系

目录 一、可见可观测 1.1 概述 1.2 服务可见性 1.2.1 概述 1.2.2 服务描述 1.2.3 服务所有权 1.2.4 服务对外接口 1.2.5 服务SLA 1.2.6 服务的上下游拓扑 1.2.7 服务变更 1.2.8 服务接入和资源配额管理 1.2.9 服务线上部署和线下测试环境信息 1.3 变更可见性 1.4 …

赚钱而已,你又不是宠物,干嘛让所有人都喜欢你?

* 大家好&#xff0c;我是前端队长。前端程序员&#xff0c;2023年开始玩副业。做过AI绘画&#xff0c;公众号 AI 爆文&#xff0c;AI代写项目&#xff0c;累计变现五位数。 — 今天看到一句话说的真好&#xff1a; 太多人总想让别人喜欢自己了。有什么用&#xff0c;你又不是宠…

数据结构和算法一轮

前言 本文参考《2025年数据结构考研复习指导&#xff08;王道论坛组编&#xff09;》和相关文章&#xff0c;为考试前复习而写。 目录 前言 第一章线性表 1.1顺序表 1.2单链表 1.3循环链表 ​1.4双向链表 第二章栈和队列 2.1栈 2.2共享栈 2.3链栈 2.4队列 2.5循环…