规则引擎之Drools
规则引擎之Drools
- Drools概述
- 规则引擎构成
- 规则文件构成
- 规则体语法结构
- 规则属性
- 比较操作符
- Pattern模式匹配
- 执行指定规则
- Drools内置方法
- Drools的基本使用
- 添加依赖
- 创建kmodule.xml
- 创建JavaBean(Fact)对象
- 创建规则文件
- 执行测试
- Spring Boot整合Drools
- 添加依赖
- 创建JavaBean(Fact)对象
- 创建规则文件
- 规则引擎配置类
- 创建RuleService类
- 创建TestController
- 执行测试
- 动态规则
- 创建数据库表存储规则
- 数据库表添加规则
- 创建Mapper接口
- 加载数据库规则
- 项目启动时自动加载规则
- 提供HTTP访问接口
- 动态规则测试
Drools概述
drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中,使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。
drools官网:https://drools.org
drools源码地址:https://github.com/kiegroup/drools
规则引擎构成
三部分构成:
1.Working Memory(工作内存)2.Rule Base(规则库)3.Inference Engine(推理引擎)a.Pattern Matcher(匹配器)b.Agenda(议程)c.Execution Engine(执行引擎)
术语概述:
Working Memory:
drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,在开发应用程序时调用kieSession.insert(Object)就将Object对象插入到了工作内存中。
Fact:
将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象。Fact对象是应用和规则引擎进行数据交互的桥梁或通道。
Rule Base:
规则库,在规则文件中定义的规则都会被加载到规则库中
Pattern Matcher:
匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。
Agenda:
议程,用于存放通过匹配器进行模式匹配后被激活的规则。
Execution Engine:
执行引擎,执行Agenda中被激活的规则。
规则文件构成
规则文件的后缀为.drl。drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。
关键字 | 描述 |
---|---|
package | 包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用 |
import | 用于导入类或者静态方法 |
global | 全局变量 |
function | 自定义函数 |
query | 查询 |
rule end | 规则体 |
规则体语法结构
规则体是规则文件内容中的重要组成部分,是进行业务规则判断、处理业务结果的部分。
rule "ruleName"attributeswhenLHSthenRHS
end
关键字 | 描述 |
---|---|
rule | 关键字,表示规则开始,参数为规则的唯一名称 |
attributes | 规则属性,是rule与when之间的参数,为可选项 |
when | 关键字,后面跟规则的条件部分 |
LHS(Left Hand Side) | 是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。 |
then | 关键字,后面跟规则的结果部分 |
RHS(Right Hand Side) | 是规则的后果或行动部分的通用名称 |
end | 关键字,表示一个规则结束 |
规则属性
属性名 | 说明 |
---|---|
salience | 指定规则执行优先级 |
dialect | 指定规则使用的语言类型,取值为java和mvel |
enabled | 指定规则是否启用 |
activation-group | 激活分组,具有相同分组名称的规则只能有一个规则触发 |
no-loop | 防止死循环 |
salience属性
用于指定规则的执行优先级,取值类型为Integer。数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。
rule "rules1"wheneval(true)thenSystem.out.println("1");
endrule "rules2"salience 100wheneval(true)thenSystem.out.println("2");
end
enabled属性
取值为true和false,默认值为true。用于指定当前规则是否启用,如果设置的值为false则当前规则无论是否匹配成功都不会触发
rule "rules1"enabled falsewhen$course:Course(score ==60)then$course.setRating("C级");
end
activation-group属性
指激活分组,取值为String类型。具有相同分组名称的规则只能有一个规则被触发。
rule "rules1"activation-group "myGroup"when$course:Course(score==60)thenSystem.out.println("activation-group");
endrule "rules2"activation-group "myGroup"salience 100when$course:Course(score==60)thenSystem.out.println("activation-group");
end
no-loop属性
用于防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环。取值类型为Boolean,默认值为false。
rule "rules1"no-loop truewhen$course:Course(score==60)thenupdate($course);System.out.println("no-loop");
end
比较操作符
常规比较操作符
符号 | 说明 |
---|
| 大于
< | 小于
= | 大于等于
<= | 小于等于
== | 等于
!= | 不等于
特殊比较操作符
// 创建普通的JavaBean(Fact)对象
@Data
public class Course {private String name;private List<String> list;
}
符号 | 说明 | 示例 |
---|---|---|
contains | 检查一个Fact对象的某个属性值是否包含一个指定的对象值 | Course(name contains “小白”) |
not contains | 检查一个Fact对象的某个属性值是否不包含一个指定的对象值 | Course(name no contains “小白”) |
memberOf | 判断一个Fact对象的某个属性是否在一个或多个集合中 | name memberOf list |
not memberOf | 判断一个Fact对象的某个属性是否不在一个或多个集合中 | name not memberOf list |
matches | 判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配 | name matches “小.*” |
not matches | 判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配 | name not matches “小.*” |
Pattern模式匹配
在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。
pattern的语法结构为:绑定变量名:Object(Field约束)
绑定变量名可以省略,通常绑定变量名的命名一般以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。
LHS部分还可以定义多个pattern,多个pattern之间可以使用and或者or进行连接,默认连接为and。
//规则1:100分~90分并且为95分 为A级
rule "rules1"when$course:Course($score:score >=90 && score<=100) and$course2:Course(score==95)then$course.setRating("A级");System.out.println("$score = " + $score);System.out.println("course = " + $course.getScore());System.out.println("匹配规则1:A级");
end
$score = 95.0
course = 95.0
匹配规则1:A级
course = Course(score=95.0, rating=A级)
执行指定规则
满足条件的规则都会被执行,如果只想执行其中的某个规则,可以通过规则过滤器来实现执行指定规则。
//通过规则过滤器实现只执行指定规则kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rules1"));
Drools内置方法
规则文件的RHS部分的主要作用是通过插入,删除或修改工作内存中的Fact数据,来达到控制规则引擎执行的目的。
Drools提供了一些方法可以用来操作工作内存中的数据,操作完成后规则引擎会重新进行相关规则的匹配,原来没有匹配成功的规则在我们修改数据完成后有可能就会匹配成功
update方法
update方法的作用是更新工作内存中的数据,并让相关的规则重新匹配
rule "rules1"when$course:Course(score ==60)then$course.setRating("C级");
endrule "rules2"when$course:Course(score <60 && score>=50)then$course.setScore(60D);update($course);
end
insert方法
insert方法的作用是向工作内存中插入数据,并让相关的规则重新匹配
rule "rules1"when$course:Course(score ==60)then$course.setRating("C级");
endrule "rules2"when$course:Course(score <60 && score>=50)thenCourse course = new Course();course.setScore(60D);insert(course);
end
retract方法
retract方法的作用是删除工作内存中的数据,并让相关的规则重新匹配
rule "rules1"when$course:Course(score ==60)then$course.setRating("C级");
endrule "rules2"when$course:Course(score <60 && score>=50)thenCourse course = new Course();course.setScore(60D);insert(course);
endrule "rules3"
// salience 2when$course:Course(score <60 && score>=50)then$course.setScore(60D);retract($course);
end
Drools的基本使用
添加依赖
<dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.62.0.Final</version>
</dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>7.62.0.Final</version>
</dependency>
创建kmodule.xml
创建resources/META-INF/kmodule.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule"><kbase name="myKbase"><ksession name="myksession" default="true"/></kbase>
</kmodule>
创建JavaBean(Fact)对象
@Data
public class Course {/*** 分数*/private Double score;/*** 评级*/private String rating;
}
创建规则文件
创建resources/myrules(任意名称)目录,并创建规则文件resources/myrules/course.drl
IDEA默认集成了drools插件,在IDEA中可以识别drools文件并给与提示
# 逻辑包,建议包名和文件夹名一一对应。
package myrules
# 导入数据载体对象
import cn.ybzy.demo.model.Course//规则1:100分~90分为A级
rule "rules1"when$course:Course(score >=90 && score<=100)then$course.setRating("A级");System.out.println("匹配规则1:A级");
end//规则2:89分~75分为B级
rule "rules2"when$course:Course(score >=75 && score<=89)then$course.setRating("B级");System.out.println("匹配规则2:B级");
end//规则3:74分~60分为C级
rule "rules3"when$course:Course(score >=60 && score<=74)then$course.setRating("C级");System.out.println("匹配规则3:C级");
end//规则4:59分及其以下为D级
rule "rules4"when$course:Course(score<=59)then$course.setRating("D级");System.out.println("匹配规则4:D级");
end
执行测试
public static void main(String[] args) {KieServices kieServices = KieServices.Factory.get();// kieClasspathContainer容器对象; 默认自动加载META-INF/kmodule.xmlKieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();//从容器中获取会话对象,用于和规则引擎交互; default="true"指定则使用默认的,否则使用kmodule.xml中定义的ksession nameKieSession kieSession = kieClasspathContainer.newKieSession();//创建数据载体对象,设置分数,由规则引擎根据分数规则计算不同的评级Course course = new Course();course.setScore(85D);//将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配kieSession.insert(course);//激活规则引擎,如果规则匹配成功则执行规则kieSession.fireAllRules();//关闭会话kieSession.dispose();System.out.println("course = " + course);}
匹配规则2:B级
course = Course(score=85.0, rating=B级)
Spring Boot整合Drools
添加依赖
<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><drools.version>7.62.0.Final</drools.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.kie</groupId><artifactId>kie-spring</artifactId><version>${drools.version}</version><exclusions><exclusion><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></exclusion><exclusion><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></exclusion><exclusion><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></exclusion><exclusion><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></exclusion></exclusions></dependency>
创建JavaBean(Fact)对象
@Data
public class Course {/*** 分数*/private Double score;/*** 评级*/private String rating;
}
创建规则文件
创建/resources/myrules/springbootrules.drl规则文件
package myrulesimport cn.ybzy.demo.model.Courserule "rules1"wheneval(true)thenSystem.out.println("springbootrules....");
endrule "rules2"when$course:Course(score >=75 && score<=89)then$course.setRating("B级");System.out.println("匹配规则2:B级");
end
规则引擎配置类
创建配置类DroolsConfig
/*** 规则引擎配置类*/
@Configuration
public class DroolsConfig {//指定规则文件存放的目录private static final String RULES_PATH = "myrules/";private final KieServices kieServices = KieServices.Factory.get();@Bean@ConditionalOnMissingBeanpublic KieFileSystem kieFileSystem() throws IOException {KieFileSystem kieFileSystem = kieServices.newKieFileSystem();ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();Resource[] ruleFiles = resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");String path = null;for (Resource file : ruleFiles) {path = RULES_PATH + file.getFilename();kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));}return kieFileSystem;}@Bean@ConditionalOnMissingBean(KieContainer.class)public KieContainer kieContainer() throws IOException {KieRepository kieRepository = kieServices.getRepository();// kieRepository.addKieModule(kieRepository::getDefaultReleaseId);kieRepository.addKieModule(new KieModule() {@Overridepublic ReleaseId getReleaseId() {return kieRepository.getDefaultReleaseId();}});KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());kieBuilder.buildAll();return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());}@Bean@ConditionalOnMissingBean(KieSession.class)public KieSession kieSession() throws IOException {return kieContainer().newKieSession();}@Bean@ConditionalOnMissingBean(KieBase.class)public KieBase kieBase() throws IOException {return kieContainer().getKieBase();}@Bean@ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)public KModuleBeanFactoryPostProcessor kiePostProcessor() {return new KModuleBeanFactoryPostProcessor();}
}
创建RuleService类
@Service
public class RuleService {@Autowiredprivate KieBase kieBase;public void rule(){KieSession kieSession = kieBase.newKieSession();kieSession.fireAllRules();kieSession.dispose();}public void rule(Course course){KieSession kieSession = kieBase.newKieSession();kieSession.insert(course);kieSession.fireAllRules();kieSession.dispose();}
}
创建TestController
@RestController
public class TestController {@Autowiredprivate RuleService ruleService;@RequestMapping("/rule1")public String rule1() {ruleService.rule();return "success";}@RequestMapping("/rule2")public String rule2() {Course course = new Course();course.setScore(85D);ruleService.rule(course);return "success";}
}
执行测试
访问http://localhost:8080/rule
springbootrules....
匹配规则2:B级
动态规则
提供HTTP访问接口,将规则文件的内容存储在数据库中,当规则发生变化时调用此接口重新加载数据库中的规则。
创建数据库表存储规则
@Data
@TableName("rules")
public class Rules implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Long id;private String ruleName;private String content;
}
数据库表添加规则
package dynamicRulesrule "rules1"wheneval(true)thenSystem.out.println("动态规则....");
end
创建Mapper接口
@Mapper
public interface RulesMapper extends BaseMapper<Rules> {}
加载数据库规则
@Service
public class ReloadDroolsRulesService {public static KieContainer kieContainer;@Autowiredprivate RulesMapper rulesMapper;public KieContainer loadKieContainer() {List<Rules> rules = rulesMapper.selectList(null);KieServices kieServices = KieServices.Factory.get();KieRepository kieRepository = kieServices.getRepository();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();for (Rules rule : rules) {String drl = rule.getContent();kieFileSystem.write("src/main/resources/dynamicRules/" + rule.getRuleName() + ".drl", drl);}KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);kb.buildAll();kieContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());return kieContainer;}
}
项目启动时自动加载规则
@Component
@Slf4j
public class CommandLineRunnerImpl implements CommandLineRunner {@Resourceprivate ReloadDroolsRulesService reloadDroolsRulesService;@Overridepublic void run(String... args) {log.info(" load rules ...");reloadDroolsRulesService.loadKieContainer();}
}
提供HTTP访问接口
@RestController
public class RulesReloadController {@Autowiredprivate ReloadDroolsRulesService reloadDroolsRulesService;@RequestMapping("/reload")public String reload() {reloadDroolsRulesService.loadKieContainer();return "success";}@RequestMapping("/test")public String test() {KieSession kieSession = ReloadDroolsRulesService.kieContainer.newKieSession();kieSession.fireAllRules();kieSession.dispose();return "success";}
}
动态规则测试
1.访问/test接口
后修改数据库规则内容
2.访问/reload接口
后再访问/test接口
动态规则....
INFO 7152 --- [io-8080-exec-10] o.d.c.kie.builder.impl.KieContainerImpl : Start creation of KieBase: defaultKieBase
INFO 7152 --- [io-8080-exec-10] o.d.c.kie.builder.impl.KieContainerImpl : End creation of KieBase: defaultKieBase
动态修改规则....
规则引擎之Drools相关推荐
- 规则引擎JBoss Drools简介
一.简介 项目官网:Drools - Drools - Business Rules Management System (Java™, Open Source) 源码:GitHub - kiegro ...
- jboss规则引擎KIE Drools 6.3.0 Final 教程(1)
前言 目前世面上中文的KIE DROOLS Workbench(JBOSS BRMS)的教程几乎没有,有的也只有灵灵碎碎的使用机器来翻译的(翻的不知所云)或者是基于老版本的JBOSS Guvnor即5 ...
- jboss规则引擎KIE Drools 6.3.0 Final 教程(2)
使用JAVA程序调用规则-运行KIE-DROOLS上的规则 第一步:建立一个MAVEN的Java工程 POM.XML 给出pom.xml文件 <project xmlns="http: ...
- 详解:Drools规则引擎探究
引入 ▐ 问题引入 天猫奢品业务方为了吸引更多的新客,和提高会员的活跃度,做了一期活动,通过购买天猫奢品频道内的任意商品就赠送特殊积分,积分可以直接兑换限量的奢品商品.假如业务方给的规则如下: 主刃同 ...
- springboot中使用规则引擎Drools
文章目录 规则引擎的场景 规则引擎介绍 使用规则引擎的优势 规则引擎应用场景 rools介绍 Drools入门案例 规则引擎构成 Drools基础语法 springboot使用规则引擎 规则引擎的场景 ...
- drools规则引擎技术指南_物联网规则引擎技术
物联网应用程序设计与典型的IT解决方案大不相同,因为它将物理操作技术(OT)与传感器.致动器和通信设备连接起来,并将数字信息技术(IT)与数据.分析和工作流连接起来. 在企业环境中,物联网非常复杂,这 ...
- 规则引擎drools系列(一)
规则引擎 Drools 1. 问题引出 现有一个在线申请信用卡的业务场景,用户需要录入个人信息,如下图所示: //此处为伪代码 //检查用户信息合法性,返回true表示检查通过,返回false表示 ...
- 规则引擎 Drools
规则引擎 Drools 文章目录 规则引擎 Drools 1. 问题引出 2. 规则引擎概述 2.1 什么是规则引擎 2.2 使用规则引擎的优势 2.3 规则引擎应用场景 2.4 Drools介绍 3 ...
- Java规则引擎Drools急速入门
文章目录 1.Drools规则引擎简介 2.Drools API开发步骤 3.SpringBoot整合Drools案例 4.Drools基础语法 5.Drools条件语法部分 6.Drools结果操作 ...
最新文章
- CUDA 8混合精度编程
- 有源汇上下界最小费用可行流 ---- P4553 80人环游世界(拆点 + 有源汇上下界最小费用可行流)
- Java - HtmlEmail 邮件发送
- Android 实现 调用 WPS Office手机版接口
- Flutter - 弹出底部菜单Show Modal Bottom Sheet
- 在线普通话转粤语发音_香港最新悬疑侦探剧福尔摩师奶,粤语知识好难
- 学成在线--17.我的课程
- Asp.Net MVC5入门学习系列⑥
- 计算机创新发展战略,计算机行业:《智能汽车创新发展战略》征求意见稿点评...
- 前端小白案例-爱新鲜抽屉式特效制作
- python2048游戏实训报告_Python 实现 2048 游戏
- 2020区块链百强榜暨战疫优秀企业评选|链塔智库
- linux sd卡 测试软件,怎么检测SD卡内存卡是否被扩容过?
- Scrapy 抓取 当当图书2018畅销榜的所有图书
- Android攻城狮ScrollView
- (Java实习生)每日10道面试题打卡——Java基础知识篇2
- 华为领衔,“5G+摄像头”拿下双影帝,多家国产手机凭借拍照入围MWC最佳演员...
- 乐学习知选择--我的J2EE技术历程
- eclipse问题(!MESSAGE Unhandled event loop exception !STACK 0 java.lang.NullPointerException 	at org.e)
- Ubuntu 20.04折腾markdown编辑器remarkable血泪史