前言
曾经接触过一个电信移动通讯项目,每个案件大量的业务逻辑变更,但其实里面的业务改动,其实就是一些业务逻辑变动。
而程序员编写的代码也没有任何技术含量,跟着式样书逐字逐句的翻译就行。大量的if/else判断遍布整个项目,维护难度极大。
而这个drools规则引擎,可以方便的将业务的整体逻辑移出,更加方便程序的可读性。
准备
第一步,随便创建maven项目
第二步,pom的引入
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.10.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
第三步,在src\main\resources\META-INF\ 下面创建kmodule.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/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>
第四步,在src\main\resources\rules 下面创建 规则文件,规则文件可以以drl为结尾,xml为结尾。
案例一
首先创建bean
package com.hikktn.drools.entity;
/**
* @ClassName Order
* @Description 订单
* @Author lisonglin
* @Date 2021/3/27 21:46
* @Version 1.0
*/
public class Order {
private Double originalPrice;//订单原始价格,即优惠前价格
private Double realPrice;//订单真实价格,即优惠后价格
public String toString() {
return "Order{" + "originalPrice=" + originalPrice + ", realPrice=" + realPrice + '}';
}
public Double getOriginalPrice() {
return originalPrice;
}
public void setOriginalPrice(Double originalPrice) {
this.originalPrice = originalPrice;
}
public Double getRealPrice() {
return realPrice;
}
public void setRealPrice(Double realPrice) {
this.realPrice = realPrice;
}
}
创建bookDiscount.drl文件,建立相应规则
// 图书优惠策略
package book.discount;
// 引入项目
import com.hikktn.drools.entity.Order;
dialect "mvel"
// 规则一:所购图书总价在100元以下的没有优惠
rule "book_discount_1"
when
$order:Order( originalPrice < 100 ) // 模式匹配
then
$order.setRealPrice($order.getOriginalPrice());
System.out.println("没有优惠");
end
@Test
public void test2(){
// 获取规则引擎
KieServices kieServices = KieServices.Factory.get();
// 获取连接
KieContainer kieContainer = kieServices.getKieClasspathContainer();
// 创建会话1
KieSession kieSession = kieContainer.newKieSession();
// 构造订单
Order order =new Order();
order.setOriginalPrice(50.0);
// 添加事件
kieSession.insert(order);
kieSession.fireAllRules();
// 关闭会话
kieSession.dispose();
}
结果
没有优惠
案例二
两个订单不同的规则,不会触发到其他的规则
AgendaFilter 增加过滤规则
RuleNameEqualsAgendaFilter 执行名称全匹配的规则
RuleNameEndsWithAgendaFilter 执行名称以xxx结尾的规则
RuleNameMatchesAgendaFilter 可以写自己的正则
RuleNameStartsWithAgendaFilter 执行名称以xxx开头的规则
RuleNameSerializationAgendaFilter 规则名称序列化代理筛选器
// 规则四:所购图书总价在300元以上的优惠100元
rule "book_discount_4"
when
$order:Order(originalPrice >= 300)
then
$order.setRealPrice($order.getOriginalPrice() - 100);
System.out.println("优惠100元");
end
// 规则二:所购图书总价在100到200元的优惠20元
rule "book_discountA"
when
$order:Order( originalPrice < 200 && originalPrice >= 100 ) // 模式匹配
then
$order.setRealPrice($order.getOriginalPrice() - 20);
System.out.println("订单优惠了20元");
end
@Test
public void test1(){
// 获取规则引擎
KieServices kieServices = KieServices.Factory.get();
// 获取连接
KieContainer kieContainer = kieServices.getKieClasspathContainer();
// 创建会话1
KieSession kieSession = kieContainer.newKieSession();
// 创建会话2
KieSession kieSession2 = kieContainer.newKieSession();
// 构造订单
Order order =new Order();
order.setOriginalPrice(500.0);
Order order2 =new Order();
order2.setOriginalPrice(100D);
// 添加订单,针对订单进行规则交互计算
kieSession.insert(order);
kieSession2.insert(order2);
// 激活规则引擎
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("book_discount_"));
// AgendaFilter 增加过滤规则
// RuleNameEqualsAgendaFilter 执行名称全匹配的规则
// RuleNameEndsWithAgendaFilter 执行名称以xxx结尾的规则
// RuleNameMatchesAgendaFilter 可以写自己的正则
// RuleNameStartsWithAgendaFilter 执行名称以xxx开头的规则
// RuleNameSerializationAgendaFilter 规则名称序列化代理筛选器
kieSession2.fireAllRules(new RuleNameEqualsAgendaFilter("book_discountA"));
// 关闭会话
kieSession.dispose();
kieSession2.dispose();
System.out.println("订单1的原价格:"+order.getOriginalPrice()+ ",优惠价格:"+order.getRealPrice());
System.out.println("订单2的原价格:"+order.getOriginalPrice()+ ",优惠价格:"+order2.getRealPrice());
}
结果
优惠100元
订单优惠了20元
订单1的原价格:500.0,优惠价格:400.0
订单2的原价格:500.0,优惠价格:80.0
内置方法
符号 | 说明 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
contains | 检查一个Fact对象的某个属性值是否包含一个指定的对象值 |
not contains | 检查一个Fact对象的某个属性值是否不包含一个指定的对象值 |
memberOf | 判断一个Fact对象的某个属性是否在一个或多个集合中 |
not memberOf | 判断一个Fact对象的某个属性是否不在一个或多个集合中 |
matches | 判断一个Fact对象的属性是否与提供的标准的Java正则表达式进行匹配 |
not matches | 判断一个Fact对象的属性是否不与提供的标准的Java正则表达式进行匹配 |
update方法
更新工作内存中的数据,并让相关的规则重新匹配
insert方法
向工作内存中插入数据,并让相关的规则重新匹配。
retract方法
删除工作内存中的数据,并让相关的规则重新匹配。
package com.hikktn.drools.entity;
import org.kie.api.definition.type.ClassReactive;
import java.io.Serializable;
/**
* @ClassName Student
* @Description TODO
* @Author lisonglin
* @Date 2021/3/28 21:47
* @Version 1.0
*/
@ClassReactive
public class Student implements Serializable {
private int id;
private int age;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.hikktn.drools.entity;
import com.hikktn.drools.entity.Student;
// 使用java模板,内置方法必须用分号结束 mvel没有限制,除此外没有其他语言类型
dialect "mvel"
// 在drools修改属性,不希望触发内置方法,修改了bean的属性,这时在bean 那里加上@ClassReactive注解,同时drools文件声明属性
// 这里的属性必须和bean属性一致,否则报错
declare Student
id : int
age : int
name : String
end
rule "The student is under 16 years old"
when
$s:Student(age <= 16)
then
// 如果fact没有申明内容,这里的自定义可以进行修改
$s.setName("未成年");
// 修改的年纪,结果出现了变更,但是并没有触发下面一条规则
$s.setAge($s.getAge()+1);
// 这样的修改bean并没有效果
update($s)
System.out.println("这个学生的年纪小于16岁,他还是"+$s.getName()+",明年他满"+$s.getAge());
end
rule "The student is over 16 years old and younger than 30"
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age > 16 , age <= 30)
then
Student student =new Student();
student.setAge(60);
// update 不能使用,否则报错
insert(student);
$s.setName("青年");
System.out.println("这个学生的年纪大于16岁且小于30岁,他还是"+$s.getName());
end
rule "The student is under 60 years old"
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age >= 60);
then
$s.setName("老年");
System.out.println("这个学生的年纪大于60岁,他还是"+$s.getName());
end
@Test
public void test4(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student =new Student();
// 测试前面三个规则
student.setAge(16);
student.setName("未知");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
这个学生的年纪小于16岁,他还是未成年,明年他满17
这个学生的年纪大于16岁且小于30岁,他还是青年
这个学生的年纪大于60岁,他还是老年
规则属性
属性名 | 说明 |
salience | 指定规则执行优先级 |
dialect | 指定规则使用的语言类型,取值为java和mvel |
enabled | 指定规则是否启用 |
date-effective | 指定规则生效时间 |
date-expires | 指定规则失效时间 |
activation-group | 激活分组,具有相同分组名称的规则只能有一个规则触发 |
agenda-group | 议程分组,只有获取焦点的组中的规则才有可能触发 |
timer | 定时器,指定规则触发的时间 |
auto-focus | 自动获取焦点,一般结合agenda-group一起使用 |
no-loop | 防止死循环 |
enabled属性
指定当前规则是否启用,如果设置的值为false则当前规则无论是否匹配成功都不会触发。
rule "The student is 32 years old"
// 禁用/启用
enabled false
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age == 32)
then
System.out.println("这个学生今年满32岁了,他还是"+$s.getName());
end
@Test
public void test4(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student =new Student();
student.setAge(32);
student.setName("未知");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
不会输出 “这个学生今年满32岁了,他还是...”
dialect属性
指定语言类型,分为java和mvel
// 使用java模板,内置方法必须用分号结束 mvel没有限制,除此外没有其他语言类型
dialect "mvel"
salience属性
优先级,数值越大越优先
rule "The student is 31 years old"
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age == 31);
then
$s.setName("满年");
System.out.println("这个学生的年纪正好30岁,他还是"+$s.getName());
end
rule "The student is 31 years old 2"
// 优先级
salience 10
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age == 31)
then
// 删除工作内存中的fact对象,并重新分配规则
retract($s);
System.out.println("这个学生的年纪大于30岁,他还是"+$s.getName());
end
@Test
public void test4(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student =new Student();
student.setAge(31);
student.setName("未知");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
这个学生的年纪大于30岁,他还是未知
no-loop属性
循环,和java中的while( 条件 ){ } 一样
rule "The student is 33 years old"
// 死循环开启,默认关闭
no-loop false
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student( age >= 33 )
then
Thread.sleep(1000);
$s.setAge($s.getAge()+1);
System.out.println("随着时间的流逝,每过去一年,他的年龄是"+$s.getAge());
update($s);
// System.out.println("这个学生今年满32岁了,他还是"+s.getName());
end
rule "The student is under 60 years old"
when
// && 和 , 逗号性能更加优化,作用都是一样
$s:Student(age >= 60);
then
// 退出循环
$s.setAge(32);
update($s);
$s.setName("老年");
System.out.println("这个学生的年纪大于60岁,他还是"+$s.getName());
end
@Test
public void test4(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student =new Student();
student.setAge(33);
student.setName("未知");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
随着时间的流逝,每过去一年,他的年龄是34
随着时间的流逝,每过去一年,他的年龄是35
随着时间的流逝,每过去一年,他的年龄是36
随着时间的流逝,每过去一年,他的年龄是37
随着时间的流逝,每过去一年,他的年龄是38
随着时间的流逝,每过去一年,他的年龄是39
随着时间的流逝,每过去一年,他的年龄是40
随着时间的流逝,每过去一年,他的年龄是41
随着时间的流逝,每过去一年,他的年龄是42
随着时间的流逝,每过去一年,他的年龄是43
随着时间的流逝,每过去一年,他的年龄是44
随着时间的流逝,每过去一年,他的年龄是45
随着时间的流逝,每过去一年,他的年龄是46
随着时间的流逝,每过去一年,他的年龄是47
随着时间的流逝,每过去一年,他的年龄是48
随着时间的流逝,每过去一年,他的年龄是49
随着时间的流逝,每过去一年,他的年龄是50
随着时间的流逝,每过去一年,他的年龄是51
随着时间的流逝,每过去一年,他的年龄是52
随着时间的流逝,每过去一年,他的年龄是53
随着时间的流逝,每过去一年,他的年龄是54
随着时间的流逝,每过去一年,他的年龄是55
随着时间的流逝,每过去一年,他的年龄是56
随着时间的流逝,每过去一年,他的年龄是57
随着时间的流逝,每过去一年,他的年龄是58
随着时间的流逝,每过去一年,他的年龄是59
随着时间的流逝,每过去一年,他的年龄是60
这个学生的年纪大于60岁,他还是老年
activation-group属性
激活分组,取值为String类型
rule "The student is under 16 years old"
// 阻止循环
lock-on-active true
when
$s:Student(age <= 16)
then
// 如果fact没有申明内容,这里的自定义可以进行修改
$s.setName("未成年");
// 修改的年纪,结果出现了变更,但是并没有触发下面一条规则
$s.setAge($s.getAge()+1);
// 这样的修改bean并没有效果
update($s)
System.out.println("这个学生的年纪小于16岁,他还是"+$s.getName()+",明年他满"+$s.getAge()+"岁");
end
rule "test-activation-group1"
activation-group "foo"
when
$s:Student()
then
System.out.println("test-activation-group1 被触发");
end
rule "test-activation-group2"
activation-group "foo"
when
$s:Student()
then
System.out.println("test-activation-group2 被触发");
end
@Test
public void test4(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.getAgenda().getActivationGroup("foo");
Student student =new Student();
student.setName("未知");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
这个学生的年纪小于16岁,他还是未成年,明年他满1岁
test-activation-group1 被触发
加上 优先级后
rule "test-activation-group2"
// 如果加上优先级,那么会形成先触发
salience 1
activation-group "foo"
when
$s:Student()
then
System.out.println("test-activation-group2 被触发");
end
结果
test-activation-group2 被触发
这个学生的年纪小于16岁,他还是未成年,明年他满1岁
test-activation-group2 被触发
test-activation-group1 被触发
agenda-group属性和auto-focus属性
agenda-group:议程分组 ,只有获取到焦点,才能触发规则。
auto-focus :自动获取焦点。
package rules;
dialect "mvel"
rule "rule_agendagroup_1"
agenda-group "myagendagroup_1"
when
then
System.out.println("规则rule_agendagroup_1触发");
end
rule "rule_agendagroup_2"
agenda-group "myagendagroup_1"
when
eval(false)
then
System.out.println("规则rule_agendagroup_2触发");
end
//========================================================
rule "rule_agendagroup_3"
agenda-group "myagendagroup_2"
auto-focus true
when
then
System.out.println("规则rule_agendagroup_3触发");
end
rule "rule_agendagroup_4"
agenda-group "myagendagroup_2"
when
then
System.out.println("规则rule_agendagroup_4触发");
end
@Test
public void test5() {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
//设置焦点,对应agenda-group分组中的规则才可能被触发
kieSession.getAgenda().getAgendaGroup("myagendagroup_1").setFocus();
kieSession.fireAllRules();
kieSession.dispose();
}
结果
规则rule_agendagroup_3触发
规则rule_agendagroup_4触发
规则rule_agendagroup_1触发
timer属性
定时器的作用。
方式一:timer (int: <initial delay> <repeat interval>?)
第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
方式二:timer(cron: <cron expression>)
package rules;
import java.text.SimpleDateFormat
import java.util.Date
dialect "mvel"
rule "rule_timer_1"
timer (5s 2s) //含义:5秒后触发,然后每隔2秒触发一次
when
then
System.out.println("规则rule_timer_1触发,触发时间为:" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
rule "rule_timer_2"
timer (cron:0/1 * * * * ?) //含义:每隔1秒触发一次
when
then
System.out.println("规则rule_timer_2触发,触发时间为:" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
@Test
public void test6() throws InterruptedException {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
final KieSession kieSession = kieClasspathContainer.newKieSession();
new Thread(new Runnable() {
public void run() {
//启动规则引擎进行规则匹配,直到调用halt方法才结束规则引擎
kieSession.fireUntilHalt();
}
}).start();
Thread.sleep(5000);
//结束规则引擎
kieSession.halt();
kieSession.dispose();
}
结果
规则rule_timer_2触发,触发时间为:2021-04-01 00:13:06
规则rule_timer_2触发,触发时间为:2021-04-01 00:13:07
规则rule_timer_2触发,触发时间为:2021-04-01 00:13:08
规则rule_timer_2触发,触发时间为:2021-04-01 00:13:09
规则rule_timer_2触发,触发时间为:2021-04-01 00:13:10
date-effective属性
生效时间,相当于保质期。默认格式:dd-MMM-yyyy
package rules;
dialect "mvel"
rule "rule_dateexpires_1"
// 只要在2022年6月1号之前,该规则都可以生效
date-expires "01-Jun-2022"
when
then
System.out.println("规则rule_dateexpires_1触发");
end
@Test
public void test7(){
//设置日期格式
// System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
}
结果
规则rule_dateeffective_1触发
date-expires属性
失效时间,相当于生产时期。默认格式:dd-MMM-yyyy
package rules;
dialect "mvel"
rule "rule_dateexpires_1"
// 只要在2020年6月1日后,该规则都可以使用
date-expires "01-Jun-2020"
when
then
System.out.println("规则rule_dateexpires_1触发");
end
@Test
public void test7(){
//设置日期格式
// System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
}
结果
规则date-expires_1触发
global全局变量
设定全局变量
package rules;
dialect "mvel"
global java.lang.Integer count //定义一个包装类型的全局变量
global com.hikktn.drools.service.UserService userService //定义一个JavaBean类型的全局变量
global java.util.List gList //定义一个集合类型的全局变量
rule "rule_global_1"
when
then
count += 10; //全局变量计算,只对当前规则有效,其他规则不受影响
userService.save();//调用全局变量的方法
gList.add("tom");//向集合类型的全局变量中添加元素,Java代码和所有规则都受影响
gList.add("jack");
System.out.println("count=" + count);
System.out.println("gList.size=" + gList.size());
end
rule "rule_global_2"
when
then
userService.save();
System.out.println("count=" + count);
System.out.println("gList.size=" + gList.size());
end
package com.hikktn.drools.service;
/**
* @ClassName UserService
* @Description TODO
* @Author lisonglin
* @Date 2021/4/1 0:23
* @Version 1.0
*/
public class UserService {
public void save(){
System.out.println("UserService.save()...");
}
}
@Test
public void test8(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
//设置全局变量,名称和类型必须和规则文件中定义的全局变量名称对应
kieSession.setGlobal("userService",new UserService());
kieSession.setGlobal("count",5);
List list = new ArrayList();//size为0
kieSession.setGlobal("gList",list);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
UserService.save()...
count=15
gList.size=2
UserService.save()...
count=5
gList.size=2
query查询
不用返回结果的查询,返回对象
package rules;
import com.hikktn.drools.entity.Student
dialect "mvel"
//不带参数的查询
//当前query用于查询Working Memory中age<10的Student对象
query "query_1"
$student:Student(age < 10)
end
//带有参数的查询
//当前query用于查询Working Memory中age>10同时name需要和传递的参数name相同的Student对象
query "query_2"(String sname)
$student:Student(age > 20 && name == sname)
end
@Test
public void test9(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student1 = new Student();
student1.setName("张三");
student1.setAge(8);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(22);
//将对象插入Working Memory中
kieSession.insert(student1);
kieSession.insert(student2);
//调用规则文件中的查询
QueryResults results1 = kieSession.getQueryResults("query_1");
int size = results1.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results1) {
Student student = (Student) row.get("$student");
System.out.println(student);
}
//调用规则文件中的查询
QueryResults results2 = kieSession.getQueryResults("query_2","李四");
size = results2.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results2) {
Student student = (Student) row.get("$student");
System.out.println(student);
}
// 不用开启全局规则使用
// kieSession.fireAllRules();
kieSession.dispose();
}
结果
size=1
Student{id=0, age=8, name='张三'}
size=1
Student{id=0, age=22, name='李四'}
function函数
类似于JavaScript的方法,编写一个共同的方法函数,重复使用。
package rules;
import com.hikktn.drools.entity.Student
dialect "mvel"
//定义一个函数
function String sayHello(String name){
return "hello " + name;
}
rule "rule_function_1"
when
$student:Student(name != null)
then
//调用上面定义的函数
String ret = sayHello($student.getName());
System.out.println(ret);
end
@Test
public void test10(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student = new Student();
student.setName("小明");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
hello 小明
复合值限制in/not in
像SQL里面的in关键字,判断是否存在
package rules;
import com.hikktn.drools.entity.Student
dialect "mvel"
rule "in_test"
when
$s:Student(name in ("张三","李四","王五"))
then
System.out.println("学生里面有"+$s.getName());
end
rule "not_in_test"
when
$s:Student(name not in ("张三","李四","王五"))
then
System.out.println("学生里面没有"+$s.getName());
end
@Test
public void test10(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student = new Student();
student.setName("小明");
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
学生里面没有小明
条件元素eval
不推荐使用,性能不行
eval(true)
eval(false)
eval(1 == 1)
条件元素exists
继承规则
package rules;
import com.hikktn.drools.entity.Student
dialect "mvel"
rule "rule_1"
when
Student(age > 10)
then
System.out.println("规则:rule_1触发");
end
rule "rule_2" extends "rule_1" //继承上面的规则
when
/*
此处的条件虽然只写了一个,但是从上面的规则继承了一个条件,
所以当前规则存在两个条件,即Student(age < 20)和Student(age > 10)
*/
Student(age < 20)
then
System.out.println("规则:rule_2触发");
end
@Test
public void test4() {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student = new Student();
student.setAge(15);
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
}
结果
规则:rule_1触发
规则:rule_2触发
halt
终止后面所有的规则。
package rules;
dialect "mvel"
rule "rule_halt_1"
when
then
System.out.println("规则:rule_halt_1触发");
drools.halt();//立即终止后面所有规则执行
end
//当前规则并不会触发,因为上面的规则调用了halt方法导致后面所有规则都不会执行
rule "rule_halt_2"
when
then
System.out.println("规则:rule_halt_2触发");
end
@Test
public void test10(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
}
结果
规则:rule_halt_1触发