Java规则引擎Drools急速入门
文章目录
- 1.Drools规则引擎简介
- 2.Drools API开发步骤
- 3.SpringBoot整合Drools案例
- 4.Drools基础语法
- 5.Drools条件语法部分
- 6.Drools结果操作部分
- 7.Drools内置属性部分
- 8.Drools高级语法部分
1.Drools规则引擎简介
(1)什么是规则引擎
全称为业务规则管理系统,英⽂名为BRMS(即 Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。 需要注意的是规则引擎并不是一个具体的技术框架,而是指的⼀类系统,即业务规则管理系统。
目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等,使用最为广泛并且开源的是Drools。
规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出的平台。
(2)规则引擎主要的应用场景
- 风险控制系统----风险贷款、风险评估
- 反欺诈项目----银行贷款、征信验证
- 决策平台系统----财务计算
- 促销平台系统----满减、打折、加价购
(3)Drools介绍
Drools是⼀款由JBoss组织提供的基于Java语⾔开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在⽂件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、不⽤重启服务器就可以在线上环境立即生效。
Drools官网地址:https://drools.org/
drools源码下载地址:https://github.com/kiegroup/drools
(4)使用规则引擎能解决什么问题
- 硬编码实现业务规则难以维护
- 硬编码实现业务规则难以应对变化
- 业务规则发⽣变化需要修改代码,重启服务后才能生效
(5)使用规则引擎的优势
- 业务规则与系统代码分离,实现业务规则的集中管理
- 在不重启服务的情况下可随时对业务规则进行扩展和维护
- 可以动态修改业务规则,从⽽快速响应需求变更
- 规则引擎是相对独立的,只关心业务规则,使得业务分析⼈员也可以参与编辑、维护系统的业务规则
- 减少了硬编码业务规则的成本和风险
- 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单
2.Drools API开发步骤
我们在操作Drools时经常使用的API以及它们之间的关系如下图:
Kie全称为Knowledge Is Everything,即“知识就是一切”的缩写,是Jboss一系列项目的总称。
规则引擎构成
drools规则引擎由以下三部分组成:
- Working Memory(工作内存)
- Rule Base(规则库)
- Inference Engine(推理引擎)
其中Inference Engine(推理引擎)又包括:
● Pattern Matcher(匹配器) 具体匹配哪⼀个规则,由这个完成
● Agenda(议程)
● Execution Engine(执行引擎)
相关概念说明
**Working Memory:**工作内存,drools规则引擎会从Working Memory中获取数据和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要我们的数据插入到Working Memory中即可。
**Fact:**事实,是指在drools规则应用中,将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象。
**Rule Base:**规则库,我们在规则文件中定义的规则都会被加载到规则库中。
**Pattern Matcher:**匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。
**Agenda:**议程,用于存放通过匹配器进行模式匹配后被激活的规则。
**Execution Engine:**执行引擎,执行Agenda中被激活的规则。
规则引擎执行过程
3.SpringBoot整合Drools案例
(1)案例背景
某电商平台的促销活动,活动规则是根据⽤户购买订单的⾦额给⽤户送相应的积分,购买的越多送的积分越多
用户购买的金额和对应送多少积分的规则如下:
100元以下, 不加分100元-500元 加100分500元-1000元 加500分1000元 以上 加1000分
按照常理,作为一个工作一两年的开发工程师来说,这不是分分钟搞定的事情,直接上午开发,下午提测。
/*** 设置订单积分*/
public void setOrderPoint(Order order){if (order.getAmout() <= 100){order.setScore(0);}else if(order.getAmout() > 100 && order.getAmout() <= 500){order.setScore(100);}else if(order.getAmout() > 500 && order.getAmout() <= 1000){order.setScore(500);}else{order.setScore(1000);}
}
但是,假如说现在产品经理不想100元以下不送积分了,想要200元以下不送金额了,是不是又要重新改代码了。所以Drools帮我们解决在不改动原有代码的情况下修改规则的信息。
(2)创建Maven项目,加入SpringBoot依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.12</version><relativePath/></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
(3)resources下创建yml配置文件
server:port: 8888spring:application:name: drools-server
(4)创建SpringBoot启动主类
@SpringBootApplication
public class DroolsApplication {public static void main(String[] objArgs){SpringApplication.run(DroolsApplication.class, objArgs);}
}
(5)添加单元测试依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
(6)添加Drools和lombok依赖
<!--drools规则引擎--><dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>7.6.0.Final</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.6.0.Final</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-templates</artifactId><version>7.6.0.Final</version></dependency><dependency><groupId>org.kie</groupId><artifactId>kie-api</artifactId><version>7.6.0.Final</version></dependency><dependency><groupId>org.kie</groupId><artifactId>kie-spring</artifactId><version>7.6.0.Final</version></dependency><!--添加lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version><scope>compile</scope></dependency>
(7)创建订单实体类Order
/*** @description 订单实体类* @author lixiang*/
@Data
public class Order {/*** 订单金额*/private int amount;/*** 积分*/private int score;
}
(8)创建规则⽂件/resources/rules/score-rules.drl
package rulesimport com.lixiang.domain.Order//规则1:100元以下, 不加积分
rule "score_1"
when$s : Order(amount <= 100)
then$s.setScore(0);System.out.println("消费100元以下, 不加积分 ");
end//规则2:100元-500元 加100积分
rule "score_2"
when$s : Order(amount > 100 && amount <= 500)
then$s.setScore(100);System.out.println("消费100元-500元 加100积分 ");
end//规则3:500元-1000元 加500积分
rule "score_3"
when$s : Order(amount > 500 && amount <= 1000)
then$s.setScore(500);System.out.println("消费500元-1000元 加500积分 ");
end//规则4:1000元 以上 加1000积分
rule "score_4"
when$s : Order(amount > 1000)
then$s.setScore(1000);System.out.println("消费1000元 以上 加1000积分 ");
end
(9)创建DroolsConfig配置类
/*** @author lixiang* @description Drools规则引擎配置类*/
@Configuration
public class DroolsConfig {/*** 定义规则路径*/private static final String RULES_PATH = "rules/";private final KieServices kieServices = KieServices.Factory.get();/*** 获取规则文件* @return* @throws IOException*/@Bean@ConditionalOnMissingBeanpublic KieFileSystem kieFileSystem() throws IOException {KieFileSystem kieFileSystem = kieServices.newKieFileSystem();ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();Resource[] files = resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");String path;for (Resource file : files) {path = RULES_PATH + file.getFilename();kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));}return kieFileSystem;}/*** 创建Kie容器* @return* @throws IOException*/@Bean@ConditionalOnMissingBeanpublic KieContainer kieContainer() throws IOException {KieRepository kieRepository = kieServices.getRepository();kieRepository.addKieModule(kieRepository::getDefaultReleaseId);KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());kieBuilder.buildAll();return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());}@Bean@ConditionalOnMissingBeanpublic KieBase kieBase() throws IOException {return kieContainer().getKieBase();}@Bean@ConditionalOnMissingBeanpublic KModuleBeanFactoryPostProcessor kiePostProcessor() {return new KModuleBeanFactoryPostProcessor();}
}
(10)编写测试类
@SpringBootTest
public class DroolsTest {@Autowiredprivate KieBase kieBase;@Testpublic void droolsTest(){Order order = new Order();order.setAmount(200);//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();System.out.println("订单金额:"+order.getAmount()+",订单积分:"+order.getScore());}}
4.Drools基础语法
(1)规则文件的构成
drl是Drools Rule Language的缩写。在规则⽂件中编写具体的规则内容。
⼀套完整的规则文件内容构成如下:
- package:包名,package对应的不⼀定是真正的目录,可以任意写com.abc,同⼀个包下的drl文件可以相互访问
- import:用于导入类或者静态方法
- global:全局变量
- function:自定义函数
- query:查询
- rule end:规则体
(2)规则体语法构成
一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)rule "ruleName" //rule关键字,表示规则开始,参数为规则的唯⼀名称attributes //规则属性,是rule与when之间的参数,为可选项when //关键字,后⾯是规则的条件部分LHS //Left Hand Side,是规则的条件部分then //后⾯跟规则的结果部分RHS //是规则的结果或⾏为
end //表示⼀个规则的结束
5.Drools条件语法部分
LHS(Left Hand Side):是规则的条件部分的通⽤名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。
(1)约束连接
- 在 LHS 当中,可以包含 0~n 个条件,多个pattern之间可以采⽤“&&” (and) 、 “||”(or)和“,”(and)来实现,也可以不写,默认连接为and。
rule "rule1"when$s : Order(amout > 100 && amout <= 500)then$s.setScore(100);System.out.println("成功匹配到规则:100元-500元 加100积分 ");
end
- 测试代码
@Testpublic void test1(){Order order = new Order();order.setAmount(200);//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(2)比较运算符
- 在 Drools当中共提供了⼗⼆种类型的⽐较操作符, 分别是: >、 >=、 <、 <=、 = =、 !=、contains、 not contains、memberof、not memberof、matches、not matches;在这⼗⼆种类型的比较操作符当中,前六个是⽐较常⻅也是⽤的⽐较多的⽐较操作符。
符号 | 说明 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
contains | 检查一个Fact对象的某个属性值是否包含一个指定的对象值 |
not contains | 检查⼀个Fact对象的某个属性值是否不包含⼀个指定的对象值 |
memberOf | 判断⼀个Fact对象的某个属性是否在⼀个或多个集合中 |
not memberOf | 判断⼀个Fact对象的某个属性是否不在⼀个或多个集合中 |
matches | 判断⼀个Fact对象的属性是否与提供的标准的Java正则表达式进⾏匹配 |
not matches | 判断⼀个Fact对象的属性是否不与提供的标准的Java正则表达式进⾏匹配 |
验证:
- 创建订单项实体类
/*** @description 订单项* @author lixiang*/
@Data
public class OrderItem {/*** 订单项名称*/private String name;/*** 订单项金额*/private int amount;
}
- 订单中加入订单项集合
/*** @description 订单实体类* @author lixiang*/
@Data
public class Order {/*** 订单金额*/private int amount;/*** 积分*/private int score;List<OrderItem> orderItemList;
}
- 测试contains 规则
规则文件内容://测试contains规则
rule "rule1"when$orderItem:OrderItem();$order:Order(orderItemList contains $orderItem);thenSystem.out.println("测试 contains 规则触发:"+$order.getOrderItemList());
end
//java测试代码@Testpublic void test2(){Order order = new Order();order.setAmount(200);OrderItem orderItem = new OrderItem();List<OrderItem> orderItemList = new ArrayList<>();orderItemList.add(orderItem);order.setOrderItemList(orderItemList);//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
- 测试not contains 规则
规则文件内容://测试not contains规则
rule "rule1"when$orderItem:OrderItem();$order:Order(orderItemList contains $orderItem);thenSystem.out.println("测试not contains 规则触发:"+$order.getOrderItemList());
end
//java测试代码@Testpublic void test3(){Order order = new Order();order.setAmount(200);OrderItem orderItem = new OrderItem();List<OrderItem> orderItemList = new ArrayList<>();orderItemList.add(orderItem);//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
- 测试matches规则
规则文件内容://测试⽐较操作符matches
rule "rule3"whenOrderItem(name matches "订单*")thenSystem.out.println("测试⽐较操作符matches触发...");
end
//java测试代码@Testpublic void test3(){OrderItem orderItem = new OrderItem();orderItem.setName("订单项1");//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule3"));//关闭会话kieSession.dispose();}
- 测试not matches规则
规则文件内容://测试⽐较操作符not matches
rule "rule4"whenOrderItem(name not matches "订单1.*")thenSystem.out.println("测试⽐较操作符not matches触发...");
end
//java测试代码@Testpublic void test3(){OrderItem orderItem = new OrderItem();orderItem.setName("订单项1");//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));//关闭会话kieSession.dispose();}
- 测试memberOf规则
规则文件内容://测试⽐较操作符memberOf
rule "rule5"whenOrder(orderItemList memberOf list)thenSystem.out.println("测试⽐较操作符memberOf触发...");
end
//java测试代码@Testpublic void test4(){Order order = new Order();OrderItem orderItem = new OrderItem();List<OrderItem> orderItemList = new ArrayList<>();orderItemList.add(orderItem);order.setOrderItemList(orderItemList);//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule5"));//关闭会话kieSession.dispose();}
- 测试not memberOf规则
规则文件内容://测试⽐较操作符memberOf
rule "rule6"when$orderItem:OrderItem();Order($orderItem not memberOf orderItemList);thenSystem.out.println("测试⽐较操作符not memberOf触发...");
end
@Testpublic void test4(){Order order = new Order();OrderItem orderItem = new OrderItem();//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.insert(order);kieSession.insert(orderItem);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule6"));//关闭会话kieSession.dispose();}
6.Drools结果操作部分
在Drools当中,在RHS里面,提供了一些对当前Working Memory实现快速操作的宏函数或对象,比如insert/insertLogical、update和retract就可以实现对当前Working Memory中的Fact对象进行新增、删除或者是修改。
(1)insert/insertLogical函数
函数insert的作用与我们在java类当中调用StatefulKnowIedgeSession对象的insert方法的作用相同,都是将一个Fact对象插入到当前的Working Memory当中。
需注意:一旦调用 insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配⼀次, 对于没有设置no-loop 属性为 true 的规则,如果条件满足,不管其之前是否执行过都会在执行,这个特性不仅存在于 insert 宏函数上,后⾯介绍的 update、retract 宏函数同样具有该特性,所以在某些情况下因考虑不周调用 insert、update 或 retract 容易发生死循环。
//Drools提供的内置⽅法insert
rule "rule7"wheneval(true); //默认成⽴thenOrder order=new Order();order.setAmount(1000);insert(order);System.out.println("测试Drools提供的内置⽅法insert 触发...,order:"+order);
end
@Testpublic void test6() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule7"));//关闭会话kieSession.dispose();}
insertLogical:insertLogical 作⽤与 insert 类似,它的作用也是将⼀个 Fact 对象插入到当前的 Working Memroy 当中
(2)update函数
update函数意义与其名称⼀样, ⽤来实现对当前Working Memory当中的 Fact进⾏更新,⽤来告诉当前的 Working Memory 该 Fact 对象已经发生了变化。
//Drools提供的内置⽅法update
rule "rule8"when$order:Order(amount == 100);then$order.setAmount(1000);update($order);System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end
@Testpublic void test8() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配Order order = new Order();order.setAmount(100);kieSession.insert(order);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule8"));//关闭会话kieSession.dispose();}
(3)retract
retract用来将Wroking Memory当中某个Fact对象从Working Memory当中删除
rule "rule9"when$order:Order(amount == 100);then//retract($order); //先不执行删除System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
endrule "rule10"when$order:Order();thenSystem.out.println("order:"+$order);
end
@Testpublic void test9() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配Order order = new Order();order.setAmount(100);kieSession.insert(order);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
rule "rule9"when$order:Order(amount == 100);thenretract($order); //执行删除System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
endrule "rule10"when$order:Order();thenSystem.out.println("order:"+$order);
end
测试方法还是上面那个
7.Drools内置属性部分
Drools中提供的属性
属性名 | 说明 |
---|---|
salience | 指定规则执行优先级 |
dialect | 指定规则使用的语言类型,取值为java或者mvel |
enabled | 指定规则是否启用 |
date-effective | 指定规则生效时间 |
date-expires | 指定规则失效时间 |
activation-group | 激活分组,具有相同分组名称的规则只能有一个规则触发 |
agenda-group | 议程分组,只有获取焦点的组中的规则才有可能触发 |
timer | 定时器,指定规则触发的时间 |
auto-focus | 自动获取焦点,一般饥饿和agenda-group一起使用 |
no-loop | 防止死循环 |
(1)salience
salience用来设置规则执行的优先级,salience属性的值是一个数字,数字越大执行优先级越高。默认情况下,规则的salience默认值为0。如果不设置salience属性,规则体的执行顺序为由上到下。
rule "rule1"salience 1wheneval(true)thenSystem.out.println("执行规则1");
end
rule "rule2"salience 2wheneval(true)thenSystem.out.println("执行规则2");
end
@Testpublic void test10() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(2)no-loop
no-loop是用来控制已经执行过的规则在条件再次满足的时候是否再次执行。no-loop属性是一个布尔型默认情况下规则的no-loop属性的值为false,如果no-loop属性值为true,那么就表示该规则只会被引擎检查一次。
//这是一个死循环修改,永远都会被匹配到修改
rule "rule3"when$order:Order(amount == 100);then$order.setAmount(100);update($order);System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end
@Testpublic void test10() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配Order order = new Order();order.setAmount(100);kieSession.insert(order);//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
//这是一个死循环修改,永远都会被匹配到修改
rule "rule3"no-loop true //配置no-loop属性when$order:Order(amount == 100);then$order.setAmount(100);update($order);System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end
再次测试
(3)date-effective
date-effective的作用是来控制规则只有达到指定的时候后才会触发,只有当系统时间大于等于date-effective设置的时间值时,规则才会被执行。
date-effective 的值为⼀个日期型的字符串,默认情况下,date-effective 可接受的日期格式为 “dd-MM-yyyy”。
在实际使用中,如果不想使用这种格式,也可以通过java代码去设置System.setProperty(String key,String value)方法来修饰默认的时间格式。
System.setProperty("drools.dateformat","yyyy-MM-dd");
rule "rule4"date-effective "2022-11-30"wheneval(true);thenSystem.out.println("测试Drools date-effective ");
end
@Testpublic void test10() {//设置时间格式System.setProperty("drools.dateformat","yyyy-MM-dd");//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));//关闭会话kieSession.dispose();}
(4)date-expires
date-expires的作用正好与date-effective属性恰恰相反,date-expires的作用时用来设置规则的有效期,引擎在执行规则的时候,会检查规则有没有date-expires属性,如果有的话,那么将这个属性与当前系统时间进行比较,如果大于系统时间就执行。
rule "rule5"date-expires "2022-11-30"wheneval(true);thenSystem.out.println("测试Drools date-effective ");
end
@Testpublic void test10() {//设置时间格式System.setProperty("drools.dateformat","yyyy-MM-dd");//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));//关闭会话kieSession.dispose();}
(5)enabled
enabled的作用就是定义一个规则是否可用。该属性的值是一个布尔值默认该属性的值为true,表示规则是可用的。设置enabled属性为false时,该规则引擎不会执行。
rule "rule1"enabled truewheneval(true)thenSystem.out.println("执行规则1");
end
rule "rule2"enabled falsewheneval(true)thenSystem.out.println("执行规则2");
end
@Testpublic void test11() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(6)dialect
dialect作用是用来定义规则当中要使用的语言类型,目前支持两种类型的语言,mvel和java,默认情况下,如果没有手工设置的话,默认使用java语言。
(7)activation-group
activation-group的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,在执行规则时,具有相同activation-group属性的规则中只要有一个会被执行,其他规则将不再执行。当然具有相同activation-group属性的规则中哪一个会先执行,可以设置salience属性来实现。
rule "rule1"activation-group "test"wheneval(true)thenSystem.out.println("执行规则1");
end
rule "rule2"activation-group "test"wheneval(true)thenSystem.out.println("执行规则2");
end
@Testpublic void test11() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(8)agenda-group
agenda-group属性是一个字符串,不过通过这个字符串可以分为若干个AgendaGroup,默认情况下,引擎在调用这些设置了agenda-group属性的规则的时候需要显示的指定某个Agenda Group得到Focus,这样位于该Agenda Group当中的规则才会触发执行,否则将不执行。
rule "rule1"agenda-group "001"wheneval(true)thenSystem.out.println("执行规则1");
end
rule "rule2"agenda-group "002"wheneval(true)thenSystem.out.println("执行规则2");
end
@Testpublic void test11() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//获取执行焦点kieSession.getAgenda().getAgendaGroup("002").setFocus();//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(9)auto-focus
auto-focus的作用是在已经设置了agenda-group的规则上设置该规则是否可以自动独取Focus,如果该属性设置为true,那么在执行引擎时,就不需要设置Focus。
rule "rule1"agenda-group "001"auto-focus truewheneval(true)thenSystem.out.println("执行规则1");
end
rule "rule2"agenda-group "002"wheneval(true)thenSystem.out.println("执行规则2");
end
@Testpublic void test11() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//激活规则引擎,如果匹配成功则执行kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(10)timer
timer属性可以通过定时器的方式指定规则执⾏的时间,使⽤方式有两种
方式一:timer(int ?)
此方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
方式二:timer(cron)
此方式使用标准的unix cron 表达式的使用来定义规则执行的时间。
rule "rule_timer_1"timer (5s 2s) //含义:5秒后触发,然后每隔2秒触发⼀次whenthenSystem.out.println("规则rule_timer_1触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
endrule "rule_timer_2"timer (cron:0/1 * * * * ?) //含义:每隔1秒触发⼀次whenthenSystem.out.println("规则rule_timer_2触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
@Testpublic void test12() throws InterruptedException {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配//启动规则引擎进行规则匹配,知道调用halt方法才结束引擎new Thread(kieSession::fireUntilHalt).start();//当前线程睡眠10sThread.sleep(10000L);//调用haltkieSession.halt();//关闭会话kieSession.dispose();}
8.Drools高级语法部分
关键字 | 描述 |
---|---|
package | 包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用 |
import | 用于导入类或者静态方法 |
global | 全局变量 |
function | 自定义函数 |
query | 查询 |
rule end | 规则体 |
(1)global全局变量
全局变量,一般用作执行规则后的结果数据返回或对具体某个服务调用等。在调用规则引擎的集成代码中,获取emailService对象,然后将其设置在工作内存中。
语法结构为:global对象类型 对象名称
import java.lang.String;global java.lang.String name;rule "rule6"wheneval(true);thenSystem.out.println("测试Global--全局order:"+name);
end
@Testpublic void test14() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.setGlobal("name","李祥");kieSession.fireAllRules();//关闭会话kieSession.dispose();}
(2)query查询
query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定"when"和"then"部分。Query有一个可选参数集合,每一个参数都可选的类型。如果没有指定类型,则默认为Object类型。引擎会尝试转为需要的类型。对于KieBase来说,query的名字是全局性的,因此不要向同一RuleBase的不同包添加相同名称的query。
使用ksession.getQueryResult(“name”)方法可以获得查询的结果,其中name为query的名称,方法的返回结果一个列表,从中可以获取匹配查询到的对象。
import com.lixiang.domain.Order;//不带参数的进行查询
query "query-1"$order : Order(amount == 100)
end
//带参数的进行查询
query "query-2"(Integer amountParam)$order : Order(amount == amountParam)
end
@Testpublic void test14() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配Order order1 = new Order();order1.setAmount(1000);Order order2 = new Order();order2.setAmount(100);//添加到工作空间kieSession.insert(order1);kieSession.insert(order2);kieSession.fireAllRules();QueryResults queryResults = kieSession.getQueryResults("query-1");System.out.println("无查询参数:result size is "+queryResults.size());for (QueryResultsRow queryResult : queryResults) {Order order = (Order)queryResult.get("$order");System.out.println("查询出来的结果:"+order);}System.out.println("------------------------------------------");QueryResults queryResults1 = kieSession.getQueryResults("query-2",1000);System.out.println("有查询参数:result size is "+queryResults1.size());for (QueryResultsRow queryResult : queryResults) {Order order = (Order)queryResult.get("$order");System.out.println("查询出来的结果:"+order);}//关闭会话kieSession.dispose();}
(3)function函数
在规则中可以通过函数来做一些通用的逻辑,就相当于java类中的方法一样。
//定义函数
function String format(String name){return "hello "+name;
}rule "function_rule"wheneval(true);then//调⽤上⾯定义的函数String ret = format("李祥");System.out.println(ret);
end
@Testpublic void test13() {//创建会话对象,用于和规则交互的引擎KieSession kieSession = kieBase.newKieSession();//讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配kieSession.fireAllRules();//关闭会话kieSession.dispose();}
Java规则引擎Drools急速入门相关推荐
- java排班_使用java规则引擎Drools自动排班前言.doc
使用java规则引擎Drools自动排班前言 使用java规则引擎Drools自动排班前言本文以一个经简化的运输车队自动排班需求为例,详细讲解了如何使用java规则引擎Drools进行商业规则的形式语 ...
- [Drools]JAVA规则引擎 -- Drools
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
- 【Drools规则引擎】基础入门案例五(Kie-Server+WorkBench)
[Drools规则引擎]基础入门案例五(Kie-Server+WorkBench) 介绍 搭建WorkBench 搭建Kie-Server 使用WorkBench 访问登入 客户端测试 介绍 java ...
- Java开源的规则引擎 Drools 电商行业实战(含完整代码)
前言 我所在项目组刚好接到一个领取优惠券需求,具体需求是用户领取的各种类型的优惠券(比如:代金券.折扣券)数量不能超过某个自定义数量,因考虑到领取限制数量是动态的,另外考虑到扩展性,满足将来业务规则的 ...
- activiti入门系列文章14 - 集成规则引擎drools
activiti如何集成规则引擎drools呢 三个步骤: 1.pom加入依赖,activiti引擎集成部署器 1.首先进行drools规则编写.然后挂到流程图节点上 2.进行规则文件和bpmn流程文 ...
- 规则引擎drools系列(一)
规则引擎 Drools 1. 问题引出 现有一个在线申请信用卡的业务场景,用户需要录入个人信息,如下图所示: //此处为伪代码 //检查用户信息合法性,返回true表示检查通过,返回false表示 ...
- 规则引擎 Drools
规则引擎 Drools 文章目录 规则引擎 Drools 1. 问题引出 2. 规则引擎概述 2.1 什么是规则引擎 2.2 使用规则引擎的优势 2.3 规则引擎应用场景 2.4 Drools介绍 3 ...
- 【Drools一】值得打工人学习的规则引擎Drools
本文主要对Drools的使用业务场景做简单介绍. 规则引擎 规则引擎:全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System).规则引擎的主要思想是 ...
- 别再说你不会,规则引擎Drools了
一.为什么要使用规则引擎 有一天运营想弄一个积分策略,计算额外积分金额 ,规则如下: 订单原价金额 100以下, 不加分: 100-500 加100分: 500-1000 加500分: 1000 以上 ...
最新文章
- Android_CodeWiki_01
- 解决:No configuration found. Configuring ehcache from ehcache-failsafe.xml 问题
- selenium - 下拉框操作
- VTK:彩色海拔地图用法实战
- 决策树——ID3和C4.5
- 开发接口文档_更优更稳更好,看文档驱动开发模式在AIMS中的优势
- ios多线程之NSThread头文件详解
- 大数据之-Hadoop3.x_MapReduce_序列化概述---大数据之hadoop3.x工作笔记0094
- HDU 5752.Sqrt Bo
- 【Todo】Java类型转换总结
- 关于窗口跳转的一些总结
- PhpSpreadsheet如何读取excel文件
- C#格式化小数位的方法
- 插值算法的Python实现方式
- jvm核心技术梳理(持续更新)
- word安全模式解除方法!
- html图片有的不显示不出来的,css背景图片不显示有哪些原因?
- LOJ#10064. 「一本通 3.1 例 1」黑暗城堡
- metasploit小白教程总结
- 28个在线游戏编程学习网站