规则引擎-drools-3.2-drl文件构成-rule部分-属性Attribute

drl文件构成-rule部分

drl文件构成,位于官网的第5章位置,也是drools作为规则引擎应用的最核心部分。
其中rule模块,包括属性(Attribute - rule)、条件(Condition - when)、结果(Action - then)是5.1.7、5.1.8、5.1.9 三小节部分内容。

  1. Rule Language Reference
    官网链接:https://docs.drools.org/7.73.0.Final/drools-docs/html_single/index.html#_droolslanguagereferencechapter
    在这里插入图片描述

rule示例

rule "rule_name"
    // Attribute
    // Attribute
    when
        // Conditions
    then
        // Actions
end

rule name

其中,rule_name 是全局唯一的,意思是在kie的工作内存中需要保持唯一。所以,安全起见,在整个项目中这个rule_name保持唯一就好了。因为是字符串类型,所以,约束较少,可以使用空格、中文等。不过对于实际应用中,一般会给出有规律的命名,比如同一种类型的规则,使用相同的前缀或后缀(这样也是在后期使用时,可以利用kie的api,可以明确执行约定的规则。)

Attribute

全部属性说明

位于rule和when之间的部分,是Attribute。属性一般作用于该条规则(rule),如执行优先级、触发时间限制等。
在这里插入图片描述
每个属性在官网中都有明确的描述

Attribute Value
@ salience
An integer defining the priority of the rule. Rules with a higher salience value are given higher priority when ordered in the activation queue.
含义:salience 后面的数字越大,优先级越高
’Example: salience 10
@ enabled
A Boolean value. When the option is selected, the rule is enabled. When the option is not selected, the rule is disabled.
含义:该规则是否启用
Example: enabled true
@ date-effective
A string containing a date and time definition. The rule can be activated only if the current date and time is after a date-effective attribute.
含义:该规则从指定的日期开始生效,代码增加:System.setProperty(“drools.dateformat”, “yyyy-MM-dd”); 可以指定日期格式
Example: date-effective “4-Sep-2018”
@ date-expires
A string containing a date and time definition. The rule cannot be activated if the current date and time is after the date-expires attribute.
含义:该规则在指定日期之前生效 ,代码增加:System.setProperty(“drools.dateformat”, “yyyy-MM-dd”); 可以指定日期格式
Example: date-expires “4-Oct-2018”
@ no-loop
A Boolean value. When the option is selected, the rule cannot be reactivated (looped) if a consequence of the rule re-triggers a previously met condition. When the condition is not selected, the rule can be looped in these circumstances.
含义:该规则结果改变造成的再次满足该规则条件,不会被触发。但其他规则结果改变造成的满足条件,会再次触发该规则。
Example: no-loop true
@ agenda-group
A string identifying an agenda group to which you want to assign the rule. Agenda groups allow you to partition the agenda to provide more execution control over groups of rules. Only rules in an agenda group that has acquired a focus are able to be activated.
Example: agenda-group “GroupName”
@ activation-group
A string identifying an activation (or XOR) group to which you want to assign the rule. In activation groups, only one rule can be activated. The first rule to fire will cancel all pending activations of all rules in the activation group.
Example: activation-group “GroupName”
@ duration
A long integer value defining the duration of time in milliseconds after which the rule can be activated, if the rule conditions are still met.
Example: duration 10000
@ timer
A string identifying either int (interval) or cron timer definitions for scheduling the rule.
含义:定时器,类似于java的定时器,定义了规则允许触发的频次
Example: timer ( cron:* 0/15 * * * ? ) (every 15 minutes)
@ calendar
A Quartz calendar definition for scheduling the rule.
含义:类似于定时器,语法不同,定义了规则允许触发的时间段
Example:
// Exclude non-business hours
calendars “* * 0-7,18-23 ? * *”
// Weekdays only, as registered in the KIE session
calendars “weekday”
@ auto-focus
A Boolean value, applicable only to rules within agenda groups. When the option is selected, the next time the rule is activated, a focus is automatically given to the agenda group to which the rule is assigned.
含义:作用于 agenda groups,分组内只要有一个规则标记了 auto-focus,则名称相同的 agenda groups 分组会被触发规则。
Example: auto-focus true
@ lock-on-active
A Boolean value, applicable only to rules within rule flow groups or agenda groups. When the option is selected, the next time the ruleflow group for the rule becomes active or the agenda group for the rule receives a focus, the rule cannot be activated again until the ruleflow group is no longer active or the agenda group loses the focus. This is a stronger version of the no-loop attribute, because the activation of a matching rule is discarded regardless of the origin of the update (not only by the rule itself). This attribute is ideal for calculation rules where you have a number of rules that modify a fact and you do not want any rule re-matching and firing again.
含义:无论规则结果是否修改,该规则至多触发一次。
Example: lock-on-active true
@ ruleflow-group
A string identifying a rule flow group. In rule flow groups, rules can fire only when the group is activated by the associated rule flow.
含义:规则流
Example: ruleflow-group “GroupName”
@ dialect
A string identifying either JAVA or MVEL as the language to be used for code expressions in the rule. By default, the rule uses the dialect specified at the package level. Any dialect specified here overrides the package dialect setting for the rule.
含义:规则语言, JAVA or MVEL,默认是java
Example: dialect “JAVA”
When you use Drools without the executable model, the dialect “JAVA” rule consequences support only Java 5 syntax. For more information about executable models, see Executable rule models.

以上属性基本都是常用属性。业务场景基本覆盖的到。
便于阅读,拿出几个初学者需要会“百度一下”的属性简单介绍一下。

no-loop 和 lock-on-active

no-loop:官网定义:如果规则的结果再次触发先前满足的条件,则无法重新激活(循环)规则。
说明这个属性只能管自己的结果改变(modify、update)造成的再次触发先前满足的条件。其他规则的结果造成的,它管不了。
lock-on-active:官网定义:仅适用于 rule flow groups 或 agenda groups. 这两种分组。这是一个更强大的无循环属性版本,因为无论更新的来源如何(而不仅仅是规则本身),匹配规则的激活都会被丢弃。
先不管适用啥分组,后面这句话的意思是 no-loop的一个升级版,无论是被谁的结果条件改变造成的,该规则都最多被触发一次。

总结一句话,如果只是使用no-loop,在不了解这两个属性区别之前,会造成死循环。

文字比较抽象,举例说明:

test方法:

  @Test
    public void testLoop() {
        // 获取services
        KieServices kieServices = KieServices.Factory.get();
        // 获取container
        KieContainer container = kieServices.getKieClasspathContainer();
        // 获取session
        KieSession kieSession = container.newKieSession();

        Map<String, Object> globalMap = new HashMap<>();

        kieSession.setGlobal("globalMap", globalMap);

        Map<String, Object> conditionMap = new HashMap<>();
        conditionMap.put("age", 30);
        conditionMap.put("testKey", "test");

        kieSession.insert(conditionMap);
//        kieSession.fireAllRules();
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("map_rule_test"));
        System.out.println(globalMap.get("testKey"));
        System.out.println(conditionMap.get("userScore"));
        System.out.println(conditionMap.get("sex"));
        kieSession.dispose();
    }

map_rule.drl

package rules;

import java.util.Map
global java.util.Map globalMap

rule "map_rule_test2"
//    no-loop true
//    lock-on-active
    when
        $map:Map($map["userScore"]<600)
    then
        modify($map){put("userScore", 500)};
        System.out.println("触发了规则:map_rule_test2");
end

rule "map_rule_test1"
//    no-loop true
//    lock-on-active
    when
        $map:Map()
        Object($map["age"]>20, $map["testKey"]=="test")
    then
        modify($map){put("userScore", 300),put("sex","女")};
        globalMap.put("testKey","testValue");
        System.out.println("触发了规则:map_rule_test1");
end

  1. 其中 map_rule_test2和map_rule_test1 分别注释了
    // no-loop true
    // lock-on-active

这种情况下,执行结果:只打印 触发了规则:map_rule_test2
在这里插入图片描述
因为 规则结果部分 modify($map){put(“userScore”, 500)}; 对map进行了修改,当没有 no-loop true 这个属性时,会触发再次执行该规则,条件得到满足,所以会继续执行。从而造成死循环,且test1不会被执行到。
由于规则执行死循环,test代码中的打印也不会触发到。

当 map_rule_test1 增加了属性 no-loop true 和 lock-on-active ,对结果无影响。

  1. map_rule_test1 和 map_rule_test2 的 no-loop true 和 lock-on-active 两个属性分别注释和放开的执行结果如下截图。
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以看到 当 两个规则,都加了 no-loop true 时,仍然会造成死循环。但任意一个加上 lock-on-active true 属性的时候,则可以终止死循环。当然执行结果是不同的。因为map的初始值 score属性为null,因此当test2规则加了属性的时候,由于test1的结果修改了属性,不会再次触发test2,所以执行结果没有触发test2这个规则。

activation-group 和 agenda-group

activation-group :该属性将若干个规则划分成一个组,统一命名。在执行的时候,具有相同activation-group 属性的规则中只要有一个被执行,其它的规则都不再执行。同时可以用类似salience之类属性来实现组内规则的执行优先级。
也就是说n个规则,具有相同的属性 activation-group ,但最多只有 1 个规则会被触发,当多个规则满足条件是,默认是按照drl书写的顺序第一个被触发,但可以使用 salience 属性来约定优先级。

agenda-group :若干个agenda-group分组,每个分组内有n个规则,在执行的时候,被focus的分组,组内的所有规则都可以被触发。

举例说明:
测试方法:

 @Test
    public void testGroup() {
        // 获取services
        KieServices kieServices = KieServices.Factory.get();
        // 获取container
        KieContainer container = kieServices.getKieClasspathContainer();
        // 获取session
        KieSession kieSession = container.newKieSession();
        // 注意这行,是在代码中指定focus的分组。
//        kieSession.getAgenda().getAgendaGroup("agenda002").setFocus();
        // 触发规则
//        kieSession.fireAllRules();
        int ruleCount = kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("rule-group"));
        System.out.println("执行了规则数量:" + ruleCount);
        kieSession.dispose();
    }

group_test.drl文件

package rules;

import java.util.Date

rule "rule-group-1"
    salience 10
    activation-group "testgroup"
    when

    then
        System.out.println("activation-rule-1 .. ");
end

rule "rule-group-2"
    salience 20
    activation-group "testgroup"
    when

    then
        System.out.println("activation-rule-2 .. ");
end

rule "rule-group-3"
    agenda-group "agenda001"
    when

    then
        System.out.println("agenda001-rule-3 .. ");
end

rule "rule-group-4"
    agenda-group "agenda001"
    auto-focus
    when

    then
        System.out.println("agenda001-rule-4 .. ");
end

rule "rule-group-5"
    agenda-group "agenda002"
    when

    then
        System.out.println("agenda002-rule-5 .. ");
end

rule "rule-group-6"
    agenda-group "agenda002"
    when

    then
        System.out.println("agenda002-rule-6 .. ");
end

drl文件定义了 6 个规则,其中 activation-group “testgroup” 属性的2个、 agenda-group "agenda001"属性的2个、agenda-group "agenda002"属性的2个。
rule-group-1、rule-group-2 属性为 activation-group “testgroup” ,最多只有其中一个能执行,例子中,使用 salience 属性,将 rule-group-2 的优先级提高了。因此 rule-group-1 是不会执行到的。

agenda-group “agenda001” 因为有 auto-focus 属性,因此 rule-group-3、rule-group-4会被执行
rule-group-5、rule-group-6则不会被执行。
执行结果截图如下:
在这里插入图片描述

但代码中加入 kieSession.getAgenda().getAgendaGroup(“agenda002”).setFocus();时,
rule-group-2、 rule-group-3、rule-group-4、rule-group-5、rule-group-6,都会被执行。
执行结果截图如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值