Drools规则引擎
借鉴:基于JAVA的功能强大的开源规则引擎-Drools业务管理系统实战视频教程_哔哩哔哩_bilibili
1、什么是规则引擎?
规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。
需要注意的的规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。
规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。
2、Drools介绍
drools是一款由JBoss组织提供的基于java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。
drools官网:https://www.drools.org/
drools中文网:Drools中文网 | 基于java的功能强大的开源规则引擎
drools源码下载地址:https://github.com/kiegroup/drools
在项目中使用drools时,既可以单独使用也可以整合spring使用。如果单独使用只需导入如下maven坐标即可:
<dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.6.0.Final</version>
</dependency>
3、Drools入门案例
1、业务场景说明
业务场景:消费者在图书商城购买图书,下单后需要在支付页面显示订单优惠后的价格。具体优惠规则如下:
现在需要根据上面的规则计算优惠后的价格。
2、开发实现
第一步:创建maven工程并导入drools相关maven坐标
<!-- drools规则引擎 --><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.6.0.Final</version></dependency><!-- junit单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
第二部:根据drools要求创建resources/META-INF/kmodule.xml
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"><!--name:指定kbase的名称,可以任意,但是需要唯一packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件default:指定当前kbase是否为默认--><kbase name="myKbase1" packages="rules" default="true"><!--name:指定ksession的名称,可以任意,但需要唯一default:指定当前session是否为默认--><ksession name="ksession-rule" default="true"/></kbase>
</kmodule>
注意:上面配置文件的名字和位置都是固定写法,不能更改。
第三步:创建实体类Order
package com.ws.soon.entity;import lombok.Data;/*** 订单*/
@Data
public class Order {private Double originalPrice; // 订单原始价格,即优惠前的价格private Double realPrice; // 订单真实价格,即优惠后的价格
}
第四步:创建规则文件resources/rules/bookDiscount.drl
// 图书优惠规则
package book.discount
import com.ws.soon.entity.Order// 规则一:所购图书总价在100元以下的没有优惠
rule "book_discount_1"when$order: Order(originalPrice < 100) // 匹配模式,到规则引擎中(工作内存)查找Order对象,命名为$orderthen$order.setRealPrice($order.getOriginalPrice());System.out.println("成功匹配到规则一,所购图书总价在100元以下无优惠");
end// 规则二:所购图书总价在100~200的优惠20元
rule "book_discount_2"when$order: Order(originalPrice >= 100 && originalPrice < 200)then$order.setRealPrice($order.getOriginalPrice() - 20);System.out.println("成功匹配到规则二,所购图书总价在100~200元之间");
end// 规则三:所购图书总价在200~300元的优惠50元
rule "book_discount_3"when$order: Order(originalPrice >= 200 && originalPrice < 300)then$order.setRealPrice($order.getOriginalPrice() - 50);System.out.println("成功匹配到规则三,所购图书总价在200~300元之间");
end// 规则四:所购图书总价在300元及以上的优惠100元
rule "book_discount_4"when$order: Order(originalPrice >= 300)then$order.setRealPrice($order.getOriginalPrice() - 100);System.out.println("成功匹配到规则四,所购图书总价在300元及以上");
end
第五步:编写单元测试
package com.ws.soon.test;import com.ws.soon.entity.Order;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;public class DroolsTest {@Testpublic void test() {KieServices kieServices = KieServices.Factory.get();// 获取Kie容器对象(默认容器对象KieContainer kieContainer = kieServices.newKieClasspathContainer();// 从Kie容器对象中获取会话对象(默认session对象KieSession kieSession = kieContainer.newKieSession();Order order = new Order();order.setOriginalPrice(160d);// 将order对象插入工作内存kieSession.insert(order);System.out.println("匹配规则前优惠后价格:" + order.getRealPrice());// 匹配对象// 激活规则,由drools框架自动进行规则匹配。若匹配成功,则执行kieSession.fireAllRules();// 关闭会话kieSession.dispose();System.out.println("优惠前价格:" + order.getOriginalPrice() + "\n优惠后价格:" + order.getRealPrice());}
}
控制台输出如下:
通过上面的入门案例可以发现,使用drools引擎规则主要工作就是编写规则文件,在规则文件中定义和业务相关的业务规则,例如本案例定义的就是图书的优惠规则。规则定义好后就需要调用drools提供的api将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则,并将计算的结果返回。
可能大家会有疑问,虽然没有在代码中编写规则的判断逻辑,但是还是在规则文件中编写了业务规则,这跟在代码中编写规则有什么本质的区别?
前面已经提到,使用规则引擎时,规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。
4、小结
1、规则引擎构成
drools规则引擎由以下三部分构成:
- Working Memory(工作内存)
- Rule Base(规则库)
- Inference Engine(推理引擎)
其中Inference Engine(推理引擎)又包括:
- Pattern Matcher(匹配器)
- Agenda(议程)
- Execution Engine(执行引擎)
如下图所示:
2、相关概念说明
Working Memory:工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可,例如本案例中我们调用kieSession.insert(order);就是将order对象插入到工作内存中。
Fact:事实,是指在drools规则应用当中,将一个普通的javaBean插入到Working Memory后的对象就是Fact对象,例如本案例中的Order对象就属于Fact对象。Fact对象是我们的应用和规则引擎进行交互的桥梁或通道。
Rule Base:规则库,我们在规则文件中定义的规则都会被加载到规则库中。
Pattern Matcher:匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功则被激活并放入Agenda中。
Agenda:议程,用于存放通过匹配器进行模式匹配后被激活的规则。
Execution Engine:执行引擎,执行Agenda中被激活的规则。
3、KIE介绍
我们在操作Drools时经常使用的API以及他们之间的关系如下图:
通过上面的API可以发现,大部分类都是以Kie开头。Kie全称为Knowledge is Everything,即“只是就是一切”的缩写,是Jboss一系列项目的总称。如下图所示,Kie的主要模块有OptaPlanner、Drools、UberFire、jBPM。
通过上图可以看到,Drools是整个KIE项目中的一个组件,Drools中还包括一个Drools-WB的模块,他是一个可视化的规则编辑器。
5、Drools基础语法
1、规则文件构成
在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl。
drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。
一套完整的规则文件内容构成如下:
关键字 | 描述 |
---|---|
package | 包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用 |
import | 用于导入类或静态方法 |
global | 全景变量 |
function | 自定义函数 |
query | 查询 |
rule...end | 规则体 |
Drools支持的规则文件,除了drl形式,还有Excel文件类型的。
2、规则体语法结构
规则体是规则文件中的重要组成部分,是进行业务规则判断、处理业务结果的部分。
规则语法结构如下:
rule "ruleName" attributes when LHSthen RHS
end
rule:关键字,表示规则开始,参数为规则的唯一名称。
attribute:规则属性,是rule与when之间的参数,为可选项。
when:关键字,后面跟规则的条件部分。
LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。
then:关键字,后面跟规则的结果部分。
RHS(Right Hand Side):是规则的后果或行动部分的通用名称。
end:关键字,表示一个规则的结束。
3、注释
在drl形式的规则文件中使用注释和Java类中使用注释一致, 分为单行注释和多行注释。
单行注释用”//"进行标记,多行注释以"/*"开始,以"*/"结束。
4、Pattern匹配规则
前面我们已经知道了Drools中的匹配器可以将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,那么我们就需要在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。
pattern的语法结构为:绑定变量名:Object(Field约束)
其中绑定变量名可以省略,通常绑定变量名的命名一般建议以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false的0个或多个表达式。
例如我们的入门案例中:
// 规则二:所购图书总价在100~200的优惠20元
rule "book_discount_2"when// Order为类型约束,originalPrice为属性约束$order: Order(originalPrice >= 100 && originalPrice < 200)then$order.setRealPrice($order.getOriginalPrice() - 20);System.out.println("成功匹配到规则二,所购图书总价在100~200元之间");
end
通过上面的例子我们可以知道,匹配的条件为:
- 工作内存中必须存在Order这种类型的Fact对象---类型约束
- Fact对象的originalPrice属性值必须小于200----属性约束
- Fact对象的originalPrice属性值必须大于等 于1-0----属性约束
以上条件必须同时满足当前规则才有可能被激活。
绑定变量既可以用在对象上,也可以用在对象的属性上。例如上面的例子可以改为:
// 规则二:所购图书总价在100~200的优惠20元
rule "book_discount_2"when$order: Order($op:originalPrice >= 100 && originalPrice < 200)thenSystem.out.println("$op=" + $op);$order.setRealPrice($order.getOriginalPrice() - 20);System.out.println("成功匹配到规则二,所购图书总价在100~200元之间");
end
LHS部分还可以定义多个pattern,多个pattern之间可以使用and或者or进行连接,也可以写,默认连接为and。
5、比较操作符
符号 | 说明 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
contains | 检查一个Fact对象的某个属性值是否包含一个指定的对象值 |
not contains | 检查一个Fact对象的某个属性值是否不包含一个指定的对象值 |
memberOf | 判断一个Fact对象的某个属性是否在一个或多个集合中 |
not memberOf | 判断一个Fact对象的某个属性是否不在一个或多个集合中 |
matches | 判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配 |
not matches | 判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配 |
前6个比较操作符和Java中的完全相同,下面我们重点学习后6个比较操作符。
1、语法
●contains | not contains语法结构 // 包含与不包含,是模糊匹配,类似于sql的like
Object(Field[Collection/Array] contains value)
Object(Field[Collection/Array] npt contains value)●memberOf | not memberOf语法结构
Object(field memberOf value[Collection/Array])
Object(field not memberOf value[Collection/Array1)●matches | not matches语法结构
Object(field matches "正则表达式")
Object(field not matches "正则表达式")
2、操作步骤
第一步:创建实体类,用于测试比较运算符
package com.ws.soon.entity;import lombok.Data;import java.util.List;/*** @author wangsaisoon* @Description 实体类 用户测试比较运算符* @date 2021/10/27 21:23* @Version 1.0*/
@Data
public class ComparisonOperatorEntity {private String names;private List<String> list;
}
第二步:创建规则文件resources/rules/comparisonOperator.drl
package comparisonOperatorimport com.ws.soon.entity.ComparisonOperatorEntity/*** 当前规则用于测试drools提供的操作运算符*/// 测试比较操作符contains
rule "rule_comparison_contains"whenComparisonOperatorEntity(names contains "王小白") orComparisonOperatorEntity(list contains names)thenSystem.out.println("规则:rule_comparison_contains触发了...");
end// 测试比较操作符contains
rule "rule_comparison_not_contains"whenComparisonOperatorEntity(names not contains "王小白") andComparisonOperatorEntity(list not contains names)thenSystem.out.println("规则:rule_comparison_not_contains触发了...");
end// 测试比较操作符memberOf
rule "rule_comparison_memberOf"whenComparisonOperatorEntity(names memberOf list)thenSystem.out.println("规则:rule_comparison_memberOf触发了...");
end// 测试比较操作符not memberOf
rule "rule_comparison_not_memberOf"whenComparisonOperatorEntity(names not memberOf list)thenSystem.out.println("规则:rule_comparison_not_memberOf触发了...");
end// 测试比较操作符matches
rule "rule_comparison_matches"whenComparisonOperatorEntity(names matches "王.*") // 正则表达式thenSystem.out.println("规则:rule_comparison_matches触发了...");
end// 测试比较操作符not matches
rule "rule_comparison_not_matches"whenComparisonOperatorEntity(names not matches "王.*") // 正则表达式thenSystem.out.println("规则:rule_comparison_not_matches触发了...");
end
第三步:编写单元测试
package com.ws.soon.test;import com.ws.soon.entity.ComparisonOperatorEntity;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class ComparisonOperatorEntityTest {@Testpublic void test() {KieServices kieServices = KieServices.Factory.get();// 获取Kie容器对象(默认容器对象KieContainer kieContainer = kieServices.newKieClasspathContainer();// 从Kie容器对象中获取会话对象(默认session对象KieSession kieSession = kieContainer.newKieSession();ComparisonOperatorEntity fact = new ComparisonOperatorEntity();String names = "1王2小白";fact.setNames(names);List<String> list = new ArrayList<String>();list.add("小黑");list.add("小白");
// list.add(names);fact.setList(list);// 将order对象插入工作内存kieSession.insert(fact);// 匹配对象// 激活规则,由drools框架自动进行规则匹配。若匹配成功,则执行kieSession.fireAllRules();// 关闭会话kieSession.dispose();}
}
6、执行执行规则
6、关键字
7、Drools内置方法
Drools规则引擎相关推荐
- 详解:Drools规则引擎探究
引入 ▐ 问题引入 天猫奢品业务方为了吸引更多的新客,和提高会员的活跃度,做了一期活动,通过购买天猫奢品频道内的任意商品就赠送特殊积分,积分可以直接兑换限量的奢品商品.假如业务方给的规则如下: 主刃同 ...
- 使用 Drools 规则引擎实现业务逻辑,可调试drl文件
http://www.srcsky.com/tech/arts/389.html 代码下载http://download.csdn.net/detail/zhy011525/2462313 使用 Dr ...
- drools规则引擎因为内存泄露导致的内存溢出
进入这个问题之前,先了解一下drools: 在很多行业应用中比如银行.保险领域,业务规则往往非常复杂,并且规则处于不断更新变化中,而现有很多系统做法基本上都是将业务规则绑定在程序代码中. 主要存在的问 ...
- SpringBoot2 整合 Drools规则引擎,实现高效的业务规则
本文源码:GitHub·点这里 || GitEE·点这里 一.Drools引擎简介 1.基础简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的 ...
- SpringBoot整合Drools规则引擎动态生成业务规则
最近的项目中,使用的是flowable工作流来处理业务流程,但是在业务规则的配置中,是在代码中直接固定写死的,领导说这样不好,需要规则可以动态变化,可以通过页面去动态配置改变,所以就花了几天时间去研究 ...
- drools规则引擎 java_Drools规则引擎的使用总结
前一段时间在开发了一个做文本分析的项目.在项目技术选型的过程中,尝试使用了Drools规则引擎.让它来作为项目中有关模式分析和关键词匹配的任务.但后来,因为某种原因,还是撇开了Drools.现将这个过 ...
- 大数据风控项目实战 Drools规则引擎
可以借鉴的干货 1,统一存储服务,包含:多种存储库连接封装和服务封装 在统一存储服务 2.获取配置的环境 类:EnvVariable 一.风控项目介绍 对一个复杂支付系统提供统一.全面.高效的风险控制 ...
- drools规则引擎动态配置规则
先说下我的业务需求背景,最近公司要推出运营活动,根据用户行为送用户积分:比如用户注册送.首次消费送,非首次消费送.累积消费送.针对我们这个的特殊要求是跟具体规则绑定:比如说 规则1 用户累积消费首次达 ...
- Drools规则引擎-memberOf操作
场景 规则引擎技术讨论2群(715840230)有同学提出疑问,memberOf的使用过程中如果,memberOf之后的参数不是集合也不是数组,而是格式如"1,2,3,4"的字符串 ...
- Drools规则引擎之常用语法
一.基础api 在 Drools 当中,规则的编译与运行要通过Drools 提供的各种API 来实现,这些API 总体来讲可以分为三类:规则编译.规则收集和规则的执行.完成这些工作的API 主要有Kn ...
最新文章
- 一文读懂简化的图卷积网络GCN(SGC)| ICML 2019
- SAP卢东明:大数据同样需要小身材
- iis php根目录可以访问子目录不行,wordpress在IIS下伪静态后子目录无法访问的解决方法...
- java 迭代器只遍历了一次的解决方案
- SSM框架之关于使用JSP作为视图展示问题解决方案
- 通过反射获取DLL的类实现加载窗体
- Python 基础算法(1) - 算法简介
- 在vscode上运行linux代码,在linux上安装VSCode
- 云计算的发展及应用--演讲用PPT
- 概率论和数理统计 - 04 -
- 中断触发流程三(中断控制器)
- Linux内核之XArray
- xml引入约束示例(xsd文件)
- 性能优化工作笔记001---springcloud项目性能优化_工作经验随时更新
- 时间轮 Dialog 最简单的时间轮
- NLPCC 2021 Final Call For Papers
- 云优CMS批量翻译插件
- Win10开启卓越性能模式,比高性能更强
- flutter 如何获取屏幕的尺寸
- 京东热 key 探测框架新版发布JD-hotkey,单机 QPS 可达 35 万