赞
踩
//指定包名 package rules.sign //导入需要的类 import java.util.List import com.chy.mall.entity.Sign import org.slf4j.Logger //定义全局变量,可以定义多个全局变量 global Logger logger global List<Integer> dayCountRange //此外还可以定义function函数 、query查询等内容 //定义规则,指定规则名称。可以定义多个规则,规则内部不能再嵌套规则。 rule sign_day_7 when $sign:Sign(dayCount == 7) then $sign.setGoldCount(200); System.out.println("签到规则匹配,成功匹配到规则sign_day_7:连续签到7天送200金币"); end
drools 中的包只是逻辑上的分包,相当于命名空间,不要求和 drl 文件的物理路径保持一致,但最好保持一致,不然应用启动时会报 warn。
示例:xxx.drl 在 classpath 的 rules/sign 文件夹下,则 package 建议使用 rules.sign。
//在drl脚本中声明全局变量,此处只能声明,不能直接赋值
global Logger logger
//通过 kieSession 给全局变量赋值
kieSession.setGlobal("logger", LoggerFactory.getLogger(this.getClass()));
//指定规则名称。ruleName 可引可不引,包含空格时必须引;在同一包中,ruleName 不能重复
rule "ruleName"
attribute //设置规则属性
when
//LHS 规则条件
then
//RHS 规则计算
end
drools 处理 Fact 对象的流程:按drools加载规则的顺序,以规则为单位,逐个处理当前批次中的 Fact 对象。示例
一个drl脚本中依次定义了3个规则 rule1、2、3,规则优先级都使用默认值,则drools加载规则的先后顺序为 rule1、2、3;
一批次传递了3个Fact对象 Fact1、2、3;
处理流程:
①rule1处理当前批次中所有的Fact对象
②rule2处理当前批次中所有的Fact对象
③rule3处理当前批次中所有的Fact对象
如果一个Fact对象满足多个规则,会依次执行满足的规则。
属性可以放在 rule 中,只对该 rule 有效;也可以提到 rule 外作为全局属性配置,对所属包中的所有规则都有效。
enabled true
默认true
dialect "java"
支持 java、mvel,默认java,可以在then中写java代码
salience 100
//指定规则生效时间
date-effective "31-Dec-2021"
//指定规则失效时间
date-expires "31-Dec-2022"
默认格式 d-MMM-yyyy,比如 2021-12-31,如果操作系统是英文的,写成 “31-Jul-2017”;如果是操作系统是中文的,写成 “31-十二月-2021”。
可以使用自定义的格式,比如 “2021-12-31 10:57:00”,但需要在应用中设置 drools 使用的日期格式
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
注意:值必须与格式一一对应,比如格式是 “yyyy-MM-dd HH:mm:ss”,则值必须包含年月日时分秒,不能只有年月日,没有时分秒。
rule order_discount_3
no-loop false
when
$order:Order(originalPrice >= 100 && originalPrice <= 1000)
then
//修改作为条件的Fact对象属性
$order.setOriginalPrice($order.getOriginalPrice() * 2);
//更新Fact对象
update($order)
end
默认值 false,允许循环匹配:如果 then 中修改了作为条件的 Fact 对象属性(注意要是作为条件的属性),且使用了 update() 更新 Fact 对象,则 update() 会触发当前规则执行完后,会将更新后的 Fact 对象与之前匹配过的规则进行再次匹配,如果这轮匹配中仍然触发 update() 了,会一直循环下去,直到不满足 update() 所在规则才退出循环、继续与后续规则进行匹配。
设置为 true 则一个 Fact 对象与一个规则只匹配一次,不管有没有对 Fact 对象作为条件的属性值进行了修改,不管是否使用了 update() 更新 Fact 对象,都不会触发 Fact 对象与之前规则的再次匹配。
通常设置为 true,避免出现循环匹配,以及循环匹配造成的死循环。
lock-on-active true
lock-on-active 的使用方式、效果和 no-loop 差不多,是 no-loop 的增强版。
no-loop、lock-on-active 都用于保证对同一个 Fact 对象,一个规则只匹配一次,在drl脚本中,一般都要将 lock-on-active 或 no-loop 设置为 true,避免规则的重复匹配。
//值必须加引号
activation-group "xxx"
activation-group 将规则划分到指定激活组中,对于同一个激活组,只要当前 Fact 对象激活了其中的某个规则,就不会再与这个激活组中的其它规则匹配。
LHS 全称 Left Hand Side,可以包含 0~n 个条件,多个条件可以用 &&、|| 连接,&&也可以写成逗号,可以用小括号来区分优先级,不能使用单词形式的逻辑运算符 and、or、not。
为空时会自动添加一个条件:eval(true),此条件总是返回true,即所有 Fact 对象都满足条件。
when
$order:Order(originalPrice >= 100 && originalPrice <= 1000)
when
$order:Order(originalPrice >= 100 , originalPrice <= 1000)
条件中可以进行常见的数学运算,可以使用 >、<、==、!= 等比较运算符,可以使用 drools 内置的判断运算符,不能使用 xxx.equals()、StringUtils.isNotBlank() 等 java 代码。
常用的如下
//contains、memberOf 都可以使用字符串或集合,只要是对方的成员即可。字符串 => 只要字符串中包含即可,集合 => 等于其中某个元素即可
$user:User("男女" contains gender)
$user:User(["男","女"] contains gender)
$user:User(gender memberOf "男女")
$user:User(gender memberOf ["男","女"])
//正则表达式写成字符串格式,特殊字符要转义,比如\要使用\\
$user:User(tel matches "(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}")
Fact对象:传递给drools脚本 | 规则 的对象,在规则中可以操作 Fact 对象,访问成员属性、调用成员方法。
语法
//限制条件可选
Fact对象的数据类型(【限制条件】)
一个规则的条件匹配包括两部分:Fact对象的数据类型要匹配、限制条件要满足。
示例
rule order_discount_1 when //不带限制条件,只要Fact对象是Order类型就匹配 Order() then //... end rule order_discount_2 when //带有限制条件,需要是Order类型且要满足限制条件才匹配 Order(originalPrice >= 100 && originalPrice <= 1000) then //... end
语法
变量名:Fact对象的数据类型(【限制条件】)
示例
rule order_discount_4
when
$order:Order(originalPrice >= 100 && getOriginalPrice() <= 1000)
then
System.out.println($order.orderStatus);
System.out.println($order.getOrderStatus());
end
绑定变量名是可选的,如果要在rule中的其它地方引用,就可以绑定一个变量名,通过变量名来引用。为了好区分,变量名通常会带前缀 $ (可选)。
LHS、RHS中都可以访问Fact对象的成员(实质是调用对应的getter方法)、调用Fact对象的成员方法,LHS中可以直接访问,RHS中需要通过变量名来访问。
RHS 全称 Right Hand Side
//获取当前rule
drools.getRule()
//获取当前rule的name
drools.getRule().getName()
//获取包名
drools.getRule().getPackage()
drools.getRule().getPackageName()
insert():往工作内存中插入一个Fact对象,效果和 ksession 的 insert() 差不多。
不管是 ksession 的 insert() 还是 drools 内置的 insert(),插入时都会校验是否已插入过,如果 Fact 对象对应的引用没变,则不会再插入,复用变量时要注意这点。
示例1
Order order = new Order(200.00, null);
kieSession.insert(order);
//再次insert
order.setOriginalPrice(600.00);
kieSession.insert(order);
rule order_discount_1
when
$order:Order(originalPrice < 300)
then
//再次insert
$order.setOriginalPrice(600.00);
insert($order);
end
这2个操作,多次 insert 的 Fact 对象都指向堆中的同一个对象,在第一次 insert 这个 Fact 对象后,后续都不会再插入这个 Fact 对象。
示例2
Order order = new Order(200.00, null);
kieSession.insert(order);
//再次insert
order = new Order(600.00, null);
kieSession.insert(order);
rule order_discount_1
when
$order:Order(originalPrice < 300)
then
//再次insert
$order = new Order(600.00, null);
insert($order);
end
这2个操作,多次 insert 的 Fact 对象是堆中不同的对象,2次 insert 都会插入。
update():更新工作内存中的指定对象。
规则引擎是以 rule 为单位加载 Fact 对象,每个 rule 加载的都是最初 insert 传递给 drools | rule 的 Fact 对象,即 LRS 是以最初的 Fact 对象来判断是否满足条件,RHS 是以 Fact 对象当前的值来计算。
示例
rule order_discount_1 when $order:Order(originalPrice > 100) then //修改Fact对象的属性 $order.setOriginalPrice(1000.00); // update($order) end rule order_discount_2 when $order:Order(originalPrice > 200) then System.out.println($order.getOriginalPrice()); end rule order_discount_3 when $order:Order(originalPrice > 500) then System.out.println($order.getOriginalPrice()); end
//传递给drools一个 originalPrice=300.00 的Order对象
Order order = new Order(300.00, null);
kieSession.insert(order);
3个rule加载的Fact对象都是最初的 new Order(300.00, null),规则1、2满足条件,规则3不满足条件,规则2的 RHS 以Fact对象当前的值 originalPrice=1000.00 进行计算,输出 1000.00。
如果修改 Fact 对象后,使用drools内置方法 update() 更新 Fact 对象,则所有规则都会重新加载这个 Fact 对象,后续对此 Fact 对象的规则处理,LHS 也都是以此次更新的 Fact 对象进行条件判断。
eg. 规则1中的 update() 取消注释,则规则1、2、3都满足条件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。