1、DRools介绍

官网:https://www.drools.org/

规则引擎主要完成的就是将业务规则从代码中分离出来。

DRools一款由JBoss组织提供的基于Java语言开发的开源规则引擎,目前由 Redhat 开源的规则引擎,它是 Redhat 的 KIE Group 中的组件之一,可以比较方便的跟另一个组件 JBPM 工作流配合用于管理复杂的规则流;同时 Drools 的推理策略算法在经典 Rete 算法以及其它算法的基础上做了多个版本的增强。DRools是一个具有基于前向链接和后向链接推理的规则引擎,允许快速和可靠地评估业务规则和复杂事件处理。

关于规则引擎的说明和对比可以参考另一篇文章:规则引擎

2、DRools API开发流程

Drools API开发步骤:

  • 获取KieServices

  • 获取KieContainer

  • 获取KieSession

  • 插入Fact对象

  • 触发规则(规则需事先编写,如DRL文件或规则表等)

  • 关闭KieSession

//1.获取KieServices
KieServices kieServices = KieServices.get();
//2.获取Kie容器对象
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//3.从kie容器对象中获取会话对象
KieSession session = kieContainer.newKieSession();
//4.创建Fact对象(事实对象)
FactExample fact = new FactExample();
fact .setTest("test");
//5.将Fact对象插入到工作内存中去
session.insert(fact);
//6.激活规则,由drools框架自动进行规则匹配,如果匹配成功,则执行规则
session.fireAllRules();
//7.关闭session
session.dispose();

2.1、规则文件编码规范(建议)

  • 所有的规则文件(.drl)应统一放在一个规定的文件夹汇总,如:/rules文件夹

  • 书写的每一个规则应该尽量加上注释

  • 同一类型的对象尽量放在一个规则文件中,如所有的Student类型的对象尽量放在一个规则文件中

  • 每个规则最好都加上salience属性,明确执行顺序

  • Drools默认dialect为"java",尽量避免使用dialect "mvel"

3、DRools主要概念

3.1、规则引擎的构成

  • working Memory(工作内存)

  • Rule Base(规则库)

  • Inference Engine(推理引擎):Pattern Matcher(匹配器)、Agenda(议程)、Execution Engine(执行引擎)

3.2、规则引擎执行过程

  1. 将初始数据(fact)输入至工作内存(working Memory)

  2. 使用匹配器(Pattern Matcher)将规则库中的规则(rule)和数据(fact)匹配,匹配成功的放入到议程(Agenda)中

  3. 如果执行规则存在冲突,即同时激活了多个规则,将冲突的规则放入冲突集合(冲突是同时匹配了多条规则,不需要自己处理,drools会自动处理,也可以通过主动声明的方式限制只命中一条规则)

  4. 解决冲突,将激活的规则按顺序放入议程(Agenda)

  5. 执行议程(Agenda)中的规则,重复2-4,直到执行完毕议程中的所有规则

3.3、规则文件

3.3.1、规则文件的构成

  • package:包名,package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访问

  • import:用于导入类或者静态方法

  • global:全局变量

  • function:自定义函数

  • query:查询

  • rule end:规则体

3.3.2、规则体(rule)的基本语法

rule "ruleName"        //rule关键字,表示规则开始,参数为规则的唯一名称attributes              //规则属性,是rule与when之间的参数,为可选项when                      //关键字,后面是规则的条件部分LHS                   //Left Hand Side,是规则的条件部分then                        //后面跟规则的结果部分RHS                //是规则的结果或行为
end                          //表示一个规则的结束

3.3.3、规则体的属性

  • salience:指定规则执行的优先级,用数字表示,数字越大优先级越高。如果不设置,默认从上到下执行

  • dialect:指定规则使用的语言类型,java或mvel

  • enabled:指定规则是否启用,取值为ture或false,默认为true

  • date-effective:指定规则生效的时间

  • date-expires:指定规则失效的时间

  • timer:定时器,指定规则触发的时间

  • activation-group:激活分组,同一个组内只能有一个规则触发

  • agenda-group:议程分组,只有获取焦点的组中的规则才有可能触发。在java代码中获得焦点。

session.getAgenda().getAgendaGroup("agenda_group_name").setFocus;
  • auto-focus:自动获取焦点,一般结合agenda-group使用,取值为ture或false

  • no-loop:防止死循环,当规则使用update之类的函数修改了Fact对象时,使当前规则再次被激活从而导致死循环。

3.4、DRools的基本语法

  • 运算符:> < >= <= == !=

  • contains:检查一个Fact对象的某个属性值是否包含一个指定的对象值

  • not contains:检查一个Fact对象的某个属性值是否不包含一个指定的对象值

  • memberOf:判断一个Fact对象的某个属性是否在一个或多个集合中

  • not memberOf:判断一个Fact对象的某个属性是否不在一个或多个集合中

  • matches:判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配

  • not matcher:判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配

3.5、DRools内置方法

  • update方法:更新工作内存中的数据,并让相关的规则重新匹配。更新数据时,要注意防止陷入死循环。

  • insert方法:向工作内存中插入数据,并让相关的规则重新匹配。

  • retract方法:删除工作内存中的数据,并让相关的规则重新匹配。

3.6、DRools高级语法

3.6.1、global全局变量

global关键字用于在规则文件中定义全局变量,它可以让应用程序的对象在规则文件中能够被访问。可以用来为规则文件提供数据或服务。语法结构:global 对象类型 对象名称。

注意事项:如果对象类型为包装类时,在一个规则中改变了global的值,那么只针对当前规则有效,对其他规则中的global不会有影响。如果对象类型为集合类型或者javaBean时,在一个规则中改变了global的值,对java代码和所有规则都有效。

3.6.2、query查询

query查询提供了一种查询working memory中符合约束条件的Fact对象的简单方法。它仅包含规则文件中的LHS部分,不用指定"when"和"then"部分并且以end结束。具体语法结构如下:

query 查询的名称(可选参数)LHS
end 

3.6.3、function方法

function关键字用于在规则文件中定义函数,规则体中可以调用定义的function函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。

function 返回值类型 函数名(可选参数){//逻辑代码
}

3.6.4、LHS语法

1. 复合值限制in/not in

复合值限制是指超过一种匹配值的限制条件,类似于SQL语句中的in关键字。

$s:Student(name in ("张三","李四","王五"))
$s:Student(name not in ("张三","李四","王五"))   

2. 条件元素eval

eval用于规则体的LHS部分,并返回一个Boolean类型的值。语法结构:eval(表达式)

eval(1==1) 

3. 条件元素not

not用于判断working memory中是否存在某个Fact对象,如果不存在则返回true,存在返回true。

not Student(age<10)

4. 条件元素exists

exists与not相反,用于判断working memory中是否存在某个Fact对象,如果存在则返回true,不存在返回true。

exists Student(age<10) 

5. 规则继承

规则之间使用extends关键字进行规则部分的继承,类似于java类之间的继承。

rule "rule_1"whenStudent(age>10)thenSystem.out.println("rule_1触发");
endrule "rule_2" extends "rule_1"   //继承上面的规则whenStudent(age<20)        //此处虽然只有一个条件,但继承上面的条件,所以此处的条件是10<age<20thenSystem.out.println("rule_2触发");
end

3.6.5、RHS语法

RHS部分需要进行业务处理。在RHS部分Drools提供了一个内置对象,名称是drools,介绍几个drools对象的方法。

1. halt

halt方法的作用是立即终止后面所有规则的执行。

rule "rule_1"whenStudent(age>10)thenSystem.out.println("rule_1触发");drools.halt();     //后面的规则不再执行
endrule "rule_2" whenStudent(age<20)        thenSystem.out.println("rule_2触发");
end

2. getWorkingMemory

getRule方法的作用是返回工作内存中的对象。

rule "rule_getWorkingMemory"whenStudent(age>10)thenSystem.out.println(drools.getWorkingMemory());
end  

3.getRule

getRule方法的作用是返回规则对象。

rule "rule_getRule"whenStudent(age>10)thenSystem.out.println(drools.getRule());
end  

4、Spring Boot整合DRools

实现一个产品佣金规则计算逻辑,满足项目的规则触发条件则按照相应公式计算佣金,并返回结果。

例子业务逻辑简介:

  1. 创建maven工程并配置pom.xml

  2. 创建resources/rules/settlement.drl文件

  3. 创建domainn/ProjectRule***.java实体类

  4. 编写配置类config/DroolsAutoConfiguration.java(例子做了简化)

  5. 创建ProjectService.java

具体代码如下:

  1. 构建Spring Boot基础项目,可通过:https://start.spring.io/

  2. Maven引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version></parent><groupId>com.xxx</groupId><artifactId>drools-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>drools-demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><drools.version>7.57.0.Final</drools.version></properties><dependencies>//... Spring Boot 依赖<dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-templates</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.kie</groupId><artifactId>kie-api</artifactId><version>${drools.version}</version></dependency></dependencies>
</project>
  1. 编写规则文件DRL

//package对应的不一定是真正的目录,可以任意写com.abc,同一个包下的drl文件可以相互访问
package com.xxx;import com.xxx.droolsdemo.domain.ProjectRuleWhenCondition
import com.xxx.droolsdemo.domain.ProjectRuleWhenValue
import com.xxx.droolsdemo.domain.ProjectRuleThenCondition
import com.xxx.droolsdemo.domain.ProjectRuleThenResult
import java.math.BigDecimal
import com.sun.javafx.binding.StringFormatter
import java.util.List
import java.util.ArrayList// TODO:function定义说明
//function 返回值类型 函数名(可选参数){
//    //逻辑代码
//}function Boolean inList(List targetList, Object value){Boolean flag = false;for(Object obj : targetList){System.out.println("inList" + obj);if(obj.equals(value)){flag  = true;break;}}return flag;
}rule "product rule"salience 1          //指定优先级,数值越大优先级越高,不指定的情况下由上到下执行no-loop true        //防止陷入死循环when$thenCondition:ProjectRuleThenCondition();$thenResult:ProjectRuleThenResult();$whenCondition:ProjectRuleWhenCondition();$whenValue : ProjectRuleWhenValue(//inList($whenCondition.getPropertyTypes(),propertyType) && //户型propertyType memberOf $whenCondition.getPropertyTypes() &&area > 0 && area<$whenCondition.getArea() && //面积区间dealCount>=$whenCondition.getDealCount() ); //成交总套数thenif($thenCondition.getIsServiceFee()){$thenResult.setServiceFeeAmount($thenCondition.getReturnAmount().multiply($thenCondition.getReturnRatio()));}else{$thenResult.setServiceFeeAmount(new BigDecimal(10086));}System.out.println(drools.getRule().getName() +"被执行");
end;
  1. 构建实体

  • ProjectRuleWhenCondition:规则When条件类

  • ProjectRuleWhenValue:规则When Fact值类

  • ProjectRuleThenCondition:规则Then条件类

  • ProjectRuleThenResult:规则Then结果类

/*** 项目规则-When条件*/
@Data
public class ProjectRuleWhenCondition {/*** 物业类型*/private List<String> propertyTypes;/*** 面积*/private BigDecimal area;/*** 成交总套数*/private Integer dealCount;}
/*** 项目规则-When值*/
@Data
public class ProjectRuleWhenValue {/*** 物业类型*/private String propertyType;/*** 面积*/private BigDecimal area;/*** 成交总套数*/private Integer dealCount;}
/*** 项目规则-Then条件*/
@Data
public class ProjectRuleThenCondition {/*** 是否服务费*/private Boolean isServiceFee;/*** 回款金额*/private BigDecimal returnAmount;/*** 回款比率*/private BigDecimal returnRatio;}
/*** 项目规则-When结果*/
@Data
public class ProjectRuleThenResult {/*** 服务费(计算得出)*/private BigDecimal serviceFeeAmount;
}
  1. 构建ProjectService,实现触发逻辑

public class ProjectService {private KieContainer kieContainer;public ProjectService() {init();}public void reload() {init();}public void run() {//1. 构建when参数ProjectRuleWhenCondition whenCondition = new ProjectRuleWhenCondition();whenCondition.setPropertyTypes(Arrays.asList("住宅", "公寓", "别墅"));whenCondition.setArea(new BigDecimal(200));whenCondition.setDealCount(1);ProjectRuleWhenValuewhenValue = new ProjectRuleWhenValue();whenValue.setPropertyType("住宅");whenValue.setArea(new BigDecimal(80));whenValue.setUnitType("三房");whenValue.setDealCount(2);whenValue.setDealTotalAmount(new BigDecimal(5000));//2. 构建then参数ProjectRuleThenCondition thenCondition = new ProjectRuleThenCondition();thenCondition.setIsServiceFee(true);thenCondition.setReturnAmount(new BigDecimal(100000));thenCondition.setReturnRatio(new BigDecimal(0.2));ProjectRuleThenResult thenResult = new ProjectRuleThenResult();//3. 初始化KIE Session//KIE是JBoss提供的一套集中式管理API,@link:https://docs.jboss.org/drools/release/7.58.0.Final/kie-api-javadoc/index.htmlKieSession kieSession = kieContainer.newKieSession();kieSession.insert(whenCondition);kieSession.insert(whenValue);kieSession.insert(thenCondition);kieSession.insert(thenResult);//只执行一个符合条件的rule,需要配合salience优先级使用//kieSession.fireAllRules(1);int i = kieSession.fireAllRules();System.out.println("规则执行了" + i + "次,返回计算结果为" + thenResult.getServiceFeeAmount());kieSession.dispose();}@SneakyThrowsprivate void init() {KieServices kieServices = KieServices.get();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();Resource[] resourceArray = resourcePatternResolver.getResources("rules/**/*.drl");for (Resource file : resourceArray) {kieFileSystem.write(ResourceFactory.newClassPathResource("rules/" + file.getFilename(), "UTF-8"));}KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);kb.buildAll();KieModule kieModule = kb.getKieModule();kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());}
}
  1. 测试验证,输出结果如下

product rule被执行
规则执行了1次,返回计算结果为20000.000000000001110223024625156540423631668090820312500000

修改ProjectRuleWhenValue的值,将输出不同的结果。

参考资料

  • Spring Boot整合Drools规则引擎--以信用卡申请为例

  • DROOLS规则引擎

  • 【Drools三】打工人学习Drools高级语法

  • Drools 规则引擎探究以及在 IOT 的应用

Spring Boot整合Drools规则引擎实例相关推荐

  1. Spring Boot整合Thymeleaf模板引擎

    转载自 Spring Boot整合Thymeleaf模板引擎 什么是Thymeleaf Thymeleaf是一款用于渲染XML.XHTML.HTML5内容的模板引擎.类似Velocity,FreeMa ...

  2. SpringBoot整合Drools规则引擎动态生成业务规则

    最近的项目中,使用的是flowable工作流来处理业务流程,但是在业务规则的配置中,是在代码中直接固定写死的,领导说这样不好,需要规则可以动态变化,可以通过页面去动态配置改变,所以就花了几天时间去研究 ...

  3. SpringBoot2 整合 Drools规则引擎,实现高效的业务规则

    本文源码:GitHub·点这里 || GitEE·点这里 一.Drools引擎简介 1.基础简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的 ...

  4. Spring boot整合Drools、flowable决策引擎解决方案

    一.Drools:DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用它轻松查看业务规则 ...

  5. springboot2整合drools规则引擎(kie-spring+drools-core)

    What&Why Drools? Drools(JBoss Rules )的前身是Codehaus的一个开源项目叫Drools,后来纳入JBoss门下,更名为JBoss Rules,成为了JB ...

  6. Flink整合Drools规则引擎

    业务功能:根据告警规则,从告警流中将主告警和次告警进行关联. pom maven配置: <drools.version>6.5.0.Final</drools.version> ...

  7. java 模板引擎_极简 Spring Boot 整合 Thymeleaf 页面模板

    点击"牧码小子"关注,和众多大牛一起成长! 关注后,后台回复 java ,领取松哥为你精心准备的技术干货! 虽然现在慢慢在流行前后端分离开发,但是据松哥所了解到的,还是有一些公司在 ...

  8. Spring Boot 整合 FreeMarker 实例

    前言 在之前的文章Spring Boot 整合 Thymeleaf中,我们学习了如何将模板 Thymeleaf 整合到 Spring Boot 中,那今天我们就来看看,另一个老牌的开源免费模板引擎 - ...

  9. 黑马Drools学习笔记(一)——Drools规则引擎示例概述以及SpringBoot整合示例

    文章目录 1. 问题引出 2. 规则引擎概述 2.1 什么是规则引擎 2.2 使用规则引擎的优势 2.3 规则引擎应用场景 2.4 Drools介绍 3. Drools入门案例 3.1 业务场景说明 ...

最新文章

  1. Google Duplex语气自然流利,外媒却质疑其演示通话录音是伪造的
  2. python基础知识点大全-【python基础学习】基础重点难点知识汇总
  3. ML之SL:监督学习(Supervised Learning)的简介、应用、经典案例之详细攻略
  4. 看得懂的设计模式 享元模式python3 最基本(简单)实现
  5. IE本地网页弹出黄条“限制网页脚本”
  6. Python安装FrankMocap实现3D人体姿态估计
  7. 疲劳驾驶监测方案_【Nano Energy】TENG用于驾驶员驾驶状态监测
  8. spring整合hibernate出现HibernateException: Unable to get the default Bean Validation factory
  9. 4.9 内容代价函数
  10. STM32驱动LCD1602,哪位同学需要的,来了
  11. 产品经理面试——简历填写
  12. SVN 提示svn-base: 系统找不到指定的文件
  13. RAL 2022|基于3D语义共视图的语义SLAM精确回环检测
  14. 【优秀课设】基于Linux粤嵌GEC6818开发板的电子乐队程序设计(四种模式:和弦模式、键盘模式、鼓点模式、编曲模式)
  15. Xshell7的下载和安装
  16. Unparseable date: “2019-03-27“
  17. 部分安卓机型无法打开公众号/http链接,部分安卓机型无法打开公众号/http链接白屏
  18. Java对接微盟开放平台
  19. 嫌微信公众号排版太丑?这里让你一步到位
  20. 基于RFID技术的智能门禁系统设计(控制部分)

热门文章

  1. eclipse 或 sts 常用设置
  2. 联想重启乐檬?5G时代手机双品牌战略带来变局 1
  3. 香港买android手机,2015 Q3中国大陆/香港/台湾最热门Android手机Top 10排行榜
  4. 从RRT到RRT*,再到Informed RRT*,路径规划算法怎么写
  5. JPress企业模板-Athena
  6. AutoCAD标注显示图框处理
  7. Mac配置Java开发环境
  8. Redis初学笔记一
  9. oracle中varchar 和 nvarchar2的区别,Oracle中char,varchar,varchar2,nvarchar,nvarchar2的区别
  10. 提交App Store被拒