Easy Rules规则引擎(1-基础篇)

目录

  • 一、序言
  • 二、Easy Rules介绍
  • 三、定义规则(Rules)
    • 1、规则介绍
    • 2、编程式规则定义
    • 3、声明式规则定义
  • 四、定义事实(Facts)
  • 五、定义规则引擎(Rules Engine)
    • 1、规则引擎介绍
    • 2、InferenceRulesEngine规则引擎示例
      • (1) 定义触发条件
      • (2) 定义规则触发后的执行行为
      • (3) 测试用例

一、序言

最近团队在做一些VisaMaster卡的交易风控,运营团队提供了一些交易风控的规则,比如针对卡号MCC设置单笔交易限额,24小时交易限额,72小时交易限额等等,还有触发风控规则是否拦截交易还是只发告警邮件等等等。

虽然写各种条件判断也能实现,但是随着后面规则增加,维护成本也会越来越高,所以想尝试引入规则引擎,同时考虑到开发和学习成本,还是决定学习轻量级的Easy Rules


二、Easy Rules介绍

Easy Rules是一个Java规则引擎,它提供了规则抽象,通过触发条件和触发后的行为去创建规则。还提供了规则引擎API,通过这些API可以基于一系列的规则去判断规则是否触发,以及触发后执行什么动作。

核心特性:

  • 轻量级Java库,易于学习的API。
  • 注解式编程模型实现基于POJO开发。
  • 通过抽象定义业务规则并且轻松应用规则。
  • 支持通过简单规则可以创建组合规则。
  • 支持通过表达式语言(MVEL、SPEL和JEXL)定义规则。

相关依赖如下:

<!--Easy Rule-->
<!--核心库--><dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>4.1.0</version></dependency><!--组合规则支持--><dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-support</artifactId><version>4.1.0</version></dependency><!--SPEL表达式语言支持--><dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-spel</artifactId><version>4.1.0</version>
</dependency><!--MVEL表达式语言支持-->
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-mvel</artifactId><version>4.1.0</version>
</dependency>

三、定义规则(Rules)

1、规则介绍

大多数的业务规则可以通过如下定义来描述:

  • Name:唯一的规则名称。
  • Description:简单规则描述。
  • Priority:规则执行优先级。
  • Facts:触发规则时的一系列事实。
  • Condition:给定事实后,应该被满足的一系列条件。
  • Actions:条件满足时应该执行的一系列行为。

Easy Rules中的规则由Rule接口来代表,如下:

public interface Rule extends Comparable<Rule> {/*** 判断规则是否应该被触发,true-是,false-否*/boolean evaluate(Facts facts);/*** 规则触发后执行的行为* @throws Exception 执行时触发的异常*/void execute(Facts facts) throws Exception;
}

2、编程式规则定义

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;/*** 编程式规则定义* @author Nick Liu* @date 2023/8/3*/
public class ProgrammaticHelloWorldRule implements Rule {@Overridepublic boolean evaluate(Facts facts) {return facts.get("enabled");}@Overridepublic void execute(Facts facts) throws Exception {System.out.println("Hello World");}@Overridepublic int compareTo(Rule o) {return 0;}public static void main(String[] args) {// 定义事实Facts facts = new Facts();facts.put("enabled", true);// 注册编程式规则Rules rules = new Rules();rules.register(new ProgrammaticHelloWorldRule());// 使用默认规则引擎根据事实触发规则RulesEngine rulesEngine = new DefaultRulesEngine();rulesEngine.fire(rules, facts);}
}

备注:运行程序控制台会输出Hello World

3、声明式规则定义

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;/*** 声明式规则定义* @author Nick Liu* @date 2023/8/3*/
@Rule(name = "Hello world rule", description = "Always say hello world")
public class DeclarativeHelloWorldRule {@Conditionpublic boolean when(@Fact("enabled") boolean enabled) {return enabled;}@Action(order = 1)public void then(@Fact("enabled") boolean enabled) throws Exception {System.out.println("Hello World");}@Action(order = 2)public void finalAction(Facts facts) throws Exception {System.out.println("Final Hello World");}public static void main(String[] args) {Facts facts = new Facts();facts.put("enabled", true);Rules rules = new Rules();rules.register(new DeclarativeHelloWorldRule());RulesEngine rulesEngine = new DefaultRulesEngine();rulesEngine.fire(rules, facts);}
}

控制台运行结果如下:

Hello World
Final Hello World

四、定义事实(Facts)

在Easy Rules中,事实由Fact类来定义,如下:

public class Fact<T> {private final String name;private final T value;
}

事实有namevalue两个属性,两者都不能为空,且name属性值充当命名空间的角色需要唯一。

下面是定义事实的例子:

  • 第1种方式
Fact<String> fact = new Fact("foo", "bar");
Facts facts = new Facts();
facts.add(fact);
  • 第2种方式
Facts facts = new Facts();
facts.put("foo", "bar");

备注:两者方式都定义了一个namefoovaluebar的事实实例,第二种方式更加简洁。


五、定义规则引擎(Rules Engine)

1、规则引擎介绍

Easy Rules提供了两种规则引擎的实现:

  • DefaultRulesEngine:默认规则引擎,根据规则的自然顺序(默认为优先级)应用规则。
  • InferenceRulesEngine:推理规则引擎,持续性应用单条规则,直到规则触发条件不满足。

Easy Rules规则引擎支持下面参数配置:

参数名称参数类型必选默认值
rulePriorityThresholdintInteger.MAX_VALUE
skipOnFirstAppliedRulebooleanfalse
skipOnFirstFailedRulebooleanfalse
skipOnFirstNonTriggeredRulebooleanfalse
  • skipOnFirstAppliedRule: 当规则被触发并且成功执行行为后是否跳过下条规则。
  • skipOnFirstFailedRule : 当判断规则是否触发抛出异常或者触发成功但行为执行后抛出异常是否跳过下条规则。
  • skipOnFirstNonTriggeredRule : 当规则未被触发是否跳过下条规则。
  • rulePriorityThreshold : 如果规则优先级超过默认阈值,则跳过下条规则。

参数配置示例如下:

RulesEngineParameters parameters = new RulesEngineParameters().rulePriorityThreshold(10).skipOnFirstAppliedRule(true).skipOnFirstFailedRule(true).skipOnFirstNonTriggeredRule(true);RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

通过下面的代码可以获取规则引擎参数:

RulesEngineParameters parameters = myEngine.getParameters();

2、InferenceRulesEngine规则引擎示例

DefaultRulesEngine默认规则引擎的使用示例前面已经有提到过,下面我们看下InferenceRulesEngine推理规则引擎的代码示例。

(1) 定义触发条件

import org.jeasy.rules.api.Condition;
import org.jeasy.rules.api.Facts;/*** @author Nick Liu* @date 2023/8/5*/
public class HighTemperatureCondition implements Condition {@Overridepublic boolean evaluate(Facts facts) {int temperature = facts.get("temperature");return temperature > 25;}
}

(2) 定义规则触发后的执行行为

import org.jeasy.rules.api.Action;
import org.jeasy.rules.api.Facts;/*** @author Nick Liu* @date 2023/8/5*/
public class DecreaseTemperatureAction implements Action {@Overridepublic void execute(Facts facts) throws Exception {int temperature = facts.get("temperature");System.out.printf("Current temperature: %d, It's hot! cooling air...%n", temperature);facts.put("temperature", temperature - 1);}
}

(3) 测试用例

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.InferenceRulesEngine;
import org.jeasy.rules.core.RuleBuilder;/*** @author Nick Liu* @date 2023/8/5*/
public class AirConditionLauncher {public static void main(String[] args) {Facts facts = new Facts();facts.put("temperature", 30);// 通过规则构建API定义规则Rule rule = new RuleBuilder().name("Air Condition Rule").when(new HighTemperatureCondition()).then(new DecreaseTemperatureAction()).build();Rules rules = new Rules();rules.register(rule);// 基于事实重复应用规则的推理规则引擎,直到规则不再满足RulesEngine rulesEngine = new InferenceRulesEngine();rulesEngine.fire(rules, facts);}
}

控制台输出结果如下:

Current temperature: 30, It's hot! cooling air...
Current temperature: 29, It's hot! cooling air...
Current temperature: 28, It's hot! cooling air...
Current temperature: 27, It's hot! cooling air...
Current temperature: 26, It's hot! cooling air...

备注:可以看到定义的规则会持续触发,直到temperature的值为25。

在这里插入图片描述

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

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

相关文章

79. 单词搜索

题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 解题思路&#xff1a;递归回溯 首先遍历每一个board中的字符&#xff0c;如果该字符合word的第一个字符相等&#xff0c;就从这个位置进行匹配搜索&#xff0c;如果能够找到word&…

DataGrip 安装 与 连接MySQL数据库

DataGrip 安装 与 连接MySQL数据库 Jetbrains是著名的编程工具商业软件提供商&#xff0c;旗下有很多软件。包括IDE、团队开发工具、插件和微软.Net辅助工具、包括自创语言Kotlin等。我们通常用的和说的全家桶&#xff0c;主要就是指它的IDE套件。Jetbrains的IDE工具都支持跨平…

【算法——双指针】LeetCode 283 移动零

题目描述&#xff1a; 思路&#xff1a; (双指针) O(n)O(n)O(n) 给定一个数组 nums&#xff0c;要求我们将所有的 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 如图所示&#xff0c;数组nums [0,1,0,3,12]&#xff0c;移动完成后变成nums [1,3,12,0,0] &am…

数据库信息速递 -- MariaDB 裁员后,前景不确定 (翻译)

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请加 liuaustin3微信号 &#xff0c;在新加的朋友会分到3群&#xff…

Jmeter设置中文的两种方式,建议使用第二种

方案一 进入jmeter图像化界面&#xff0c;选择Options下的Choose Language&#xff0c;再选择Chinese(Simplified)。这个就是选择语言为简体中文&#xff08;缺陷&#xff1a;这个只是在本次使用时为中文&#xff0c;下次打开默认还是英文的&#xff09; 方案二&#xff08;…

阿里云服务器是什么?阿里云服务器有什么优缺点?

阿里云服务器是什么&#xff1f;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;云服务器可以降低IT成本提升运维效率&#xff0c;免去企业或个人前期采购IT硬件的成本&#xff0c;阿里云服务器让用户像使用水、电、天然气等公共资源一样便捷、高效地使用服务器…

基于CentOS 7 部署社区版Haproxy

HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件&#xff0c;是一款具 备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支 持正则表达式及web状态统计。 目录 1…

Mybatis三剑客(一)在springboot中自动生成Mybatis【generator】

1、pom.xml中新增plugin <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.7</version><configuration><overwrite>true</overwrite><…

const和指针的结合

目录 易错知识点 const和指针的结合 const和一级指针的结合 正误转换 巧用技巧 const是否参与类型 const和二级指针的结合 正误转换 巧用技巧 温故知新 易错知识点 1、常量不能作为左值&#xff0c;防止直接修改常量的值 2、不能将常量的地址泄露给普通指针或普通引用…

k8s基础

k8s基础 文章目录 k8s基础一、k8s组件二、k8s组件作用1.master节点2.worker node节点 三、K8S创建Pod的工作流程&#xff1f;四、K8S资源对象1.Pod2.Pod控制器3.service && ingress 五、K8S资源配置信息六、K8s部署1.K8S二进制部署2.K8S kubeadm搭建 七、K8s网络八、K8…

大语言模型(LLM)与 Jupyter 连接起来了

现在&#xff0c;大语言模型&#xff08;LLM&#xff09;与 Jupyter 连接起来了&#xff01; 这主要归功于一个名叫 Jupyter AI 的项目&#xff0c;它是官方支持的 Project Jupyter 子项目。目前该项目已经完全开源&#xff0c;其连接的模型主要来自 AI21、Anthropic、AWS、Co…

Spring AoP 详解

目录 一、概述二、Spring AOP 和 AspectJ AOP 的区别三、AspectJ 定义的通知类型四、多个切面的执行顺序控制方法 一、概述 AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关&#xff0c;却为业务模块所共同调用的逻辑或责任&#xff08;例如事务处理、日志…

【c语言】指针进阶(超详细)

文章目录 ✈ 指向函数指针数组的指针&#x1f4cc;指向函数指针数组的指针的定义&#x1f4cc;指向函数指针数组的数组指针的使用 ✈回调函数&#x1f4cc; 回调函数的定义&#x1f4cc; 回调函数的使用 ✈qsort函数&#x1f4cc; qsort函数的作用&#x1f4cc;qsort函数的定义…

【Spring Boot】构建RESTful服务 — 使用Swagger生成Web API文档

使用Swagger生成Web API文档 高质量的API文档在系统开发的过程中非常重要。本节介绍什么是Swagger&#xff0c;如何在Spring Boot项目中集成Swagger构建RESTful API文档&#xff0c;以及为Swagger配置Token等通用参数。 1.什么是Swagger Swagger是一个规范和完整的框架&…

Docker desktop使用配置

1. 下载安装 https://www.docker.com/ 官网下载并安装doker desktop 2. 配置镜像 &#xff08;1&#xff09;首先去阿里云网站上进行注册&#xff1a;https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors &#xff08;2&#xff09;注册完成后搜索&#xff1a;容…

go入门实践四-go实现一个简单的tcp-socks5代理服务

文章目录 前言socks协议简介go实现一个简单的socks5代理运行与压测抓包验证 前言 SOCKS是一种网络传输协议&#xff0c;主要用于客户端与外网服务器之间通讯的中间传递。协议在应用层和传输层之间。 本文使用先了解socks协议。然后实现一个socks5的tcp代理服务端。最后&#…

opencv实战项目 手势识别-手部距离测量

手势识别系列文章目录 手势识别是一种人机交互技术&#xff0c;通过识别人的手势动作&#xff0c;从而实现对计算机、智能手机、智能电视等设备的操作和控制。 1. opencv实现手部追踪&#xff08;定位手部关键点&#xff09; 2.opencv实战项目 实现手势跟踪并返回位置信息&…

MySQL索引和事务

目录 索引的作用 与 概念 MySQL有哪几种索引类型 如何提高查找效率 聚簇索引与非聚簇索引 覆盖索引 索引的优点和缺点 索引的一些基本操作 索引优化 B树、B树、Hash、红黑树的区别 B树与B树的区别 MySQL为什么使用B树作为索引 联合索引中的顺序 MySQL的最左前缀原…

第三节:在WORD为应用主窗口下关闭EXCEL的操作(1)

【分享成果&#xff0c;随喜正能量】夏日里的遗憾&#xff0c;一定都会被秋风温柔化解。吃素不难&#xff0c;难于不肯捨贪口腹之心。若不贪口腹&#xff0c;有何吃素之不便乎。虽吃华素&#xff0c;不吃素日&#xff0c;亦须少吃。以一切物类&#xff0c;皆是贪生怕死&#xf…

Spring Boot集成Mybatis Plus通过Pagehelper实现分页查询

文章目录 0 简要说明Pagehelper1 搭建环境1.1 项目目录1.2 项目搭建需要的依赖1.3 配置分页插件拦截器1.4 源代码启动类实体类数据层xml映射文件业务层业务层实现类控制层接口配置swagger请求体 2 可能出现的疑问或者问题2.1 关于total属性疑问2.2 分页不生效问题 3 案例说明3.…