drools規(guī)則屬性(rule attributes)的使用

一、介紹

規(guī)則屬性是您可以添加到業(yè)務(wù)規(guī)則以修改規(guī)則行為的附加規(guī)范。 在 DRL 文件中,您通常在規(guī)則條件和操作的上方定義規(guī)則屬性,多個(gè)屬性位于單獨(dú)的行中,格式如下:

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

二、常見(jiàn)的規(guī)則屬性

規(guī)則屬性 解釋 舉例
salience 定義規(guī)則優(yōu)先級(jí),是一個(gè)整數(shù)。當(dāng)在激活隊(duì)列中排序時(shí),salience的值越大,優(yōu)先級(jí)越高。 salience 99
enabled 定義規(guī)則是否啟用. true 啟用,false 禁用,默認(rèn)值是true enabled true
date-effective 包含時(shí)間和日期的字符串,當(dāng)當(dāng)前時(shí)間大于date-effective時(shí),該規(guī)則才會(huì)被激活。這個(gè)時(shí)間格式可以修改,見(jiàn)下方具體的用法 date-effective "4-5月-2022"
date-expires 設(shè)置規(guī)則的過(guò)期時(shí)間,時(shí)間格式和上方一樣。 date-expires "4-5月-2022"
no-loop 布爾值,默認(rèn)值為false, 定義當(dāng)當(dāng)前規(guī)則規(guī)則的結(jié)果修改了fact對(duì)象時(shí),是否可以再次執(zhí)行該規(guī)則。true:不可以, false:可以,可能會(huì)導(dǎo)致死循環(huán)。指的是當(dāng)前規(guī)則的修改,如果別的規(guī)則修改了,還會(huì)導(dǎo)致該規(guī)則的觸發(fā) no-loop true
agenda-group Agenda groups允許您對(duì)agenda進(jìn)行分區(qū),以提供對(duì)規(guī)則組的更多執(zhí)行控制。 只有獲得焦點(diǎn)的議程組中的規(guī)則才能被激活。 ,但是這個(gè)里面有個(gè)特例,如果某個(gè)規(guī)則沒(méi)有配置 agenda-group,但是它模式匹配成功了,那么會(huì)被分到默認(rèn)的組(main),這個(gè)main組的規(guī)則也會(huì)執(zhí)行。 agenda-group "GroupName"
auto-focus 布爾值,僅適用于Agenda-Group內(nèi)的規(guī)則。當(dāng)值為true時(shí),下次激活該規(guī)則時(shí),會(huì)將焦點(diǎn)自動(dòng)給這個(gè)Agenda group auto-focus true
activation-group 表示該組下的規(guī)則只有一個(gè)規(guī)則會(huì)被執(zhí)行,該組下其余激活的規(guī)則會(huì)被取消執(zhí)行。 但是別的組激活的規(guī)則可能會(huì)被執(zhí)行。 activation-group "GroupName"
duration long類型的值,如果在這個(gè)時(shí)間之后規(guī)則還成立,那么執(zhí)行該規(guī)則 duration 1000
timer 一個(gè)字符串,標(biāo)識(shí)用于調(diào)度規(guī)則的 int(間隔)或 cron 計(jì)時(shí)器定義。 Example: timer ( cron:* 0/15 * * * ? ) (every 15 minutes)
calendar 定義Quartz calendar用于調(diào)度規(guī)則。
lock-on-active 一個(gè)布爾值,僅適用于規(guī)則流組或議程組中的規(guī)則。 選擇該選項(xiàng)后,下次規(guī)則的規(guī)則流組變?yōu)榛顒?dòng)狀態(tài)或規(guī)則的議程組獲得焦點(diǎn)時(shí),規(guī)則無(wú)法再次激活,直到規(guī)則流組不再處于活動(dòng)狀態(tài)或議程組失去焦點(diǎn)。 這是 no-loop 屬性的更強(qiáng)版本,因?yàn)槠ヅ湟?guī)則的激活被丟棄,無(wú)論更新的來(lái)源如何(不僅是規(guī)則本身)。 此屬性非常適合計(jì)算規(guī)則,其中您有許多修改事實(shí)的規(guī)則并且您不希望任何規(guī)則重新匹配和再次觸發(fā)。 lock-on-active true
dialect 將 JAVA 或 MVEL 標(biāo)識(shí)為用于規(guī)則中的代碼表達(dá)式的語(yǔ)言的字符串。 默認(rèn)情況下,該規(guī)則使用在包級(jí)別指定的方言。 此處指定的任何方言都會(huì)覆蓋該規(guī)則的包方言設(shè)置。 dialect "JAVA"

三、部分規(guī)則屬性案例

此處編寫出規(guī)則文件和部分核心Java代碼


項(xiàng)目結(jié)構(gòu).jpg

1、salience

定義規(guī)則執(zhí)行的優(yōu)先級(jí),salience的值越大,優(yōu)先級(jí)越高

1、規(guī)則文件的編寫

rule "salience_rule_1"
    salience 4
    when
    then
        System.out.println("rule 1");
end

rule "salience_rule_2"
    salience 3
    when
    then
        System.out.println("rule 2");
end

// 此處優(yōu)先級(jí)的值是動(dòng)態(tài)獲取來(lái)的
rule "salience_rule_3"
    salience $dynamicSalience
    when
        $dynamicSalience: Integer()
    then
        System.out.println("rule 3");
end

注意:
我們的salience_rule_3的優(yōu)先級(jí)的值是動(dòng)態(tài)來(lái)的,即是從工作內(nèi)存中獲取的。

2、java代碼編寫

public class DroolsSalienceApplication {
    public static void main(String[] args) {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");

        // 向工作內(nèi)存中插入一個(gè)Integer值,salience_rule_3 需要用到這個(gè)優(yōu)先級(jí)
        kieSession.insert(10);

        // 只匹配規(guī)則名稱是已 salience_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("salience_"));

        kieSession.dispose();
    }
}

kieSession.insert(10);此處向工作內(nèi)存中插入一個(gè)值,將會(huì)匹配到salience_rule_3,然后動(dòng)態(tài)修改它的優(yōu)先級(jí)。

3、運(yùn)行結(jié)果

rule 3
rule 1
rule 2

因?yàn)?salience 的值越大優(yōu)先級(jí)越高,所以是這個(gè)順序。

2、enabled

定義規(guī)則是否啟用,true啟用 false禁用

1、規(guī)則文件編寫

package rules

rule "enabled_rule_1"
    // 禁用此規(guī)則
    enabled false
    when
    then
        System.out.println("enabled_rule_1");
end

rule "enabled_rule_2"
    // 啟用此規(guī)則,默認(rèn)就是啟用
    enabled true
    when
    then
        System.out.println("enabled_rule_2");
end

enabled_rule_2這個(gè)規(guī)則需要運(yùn)行,enabled_rule_1這個(gè)規(guī)則不能運(yùn)行。

2、java代碼編寫

/**
 * 測(cè)試規(guī)則的啟用和禁用
 */
public class DroolsEnabledApplication {
    public static void main(String[] args) {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配規(guī)則名稱是已 enabled_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("enabled_"));
        kieSession.dispose();
    }
}

沒(méi)有需要注意的地方

3、運(yùn)行結(jié)果

enabled_rule_2

可以看到只有規(guī)則enabled_rule_2輸出了結(jié)果,而enabled_rule_1被禁用了。

3、date-effective

定義規(guī)則什么時(shí)候啟用,只有當(dāng)前時(shí)間>規(guī)則時(shí)間才會(huì)啟用。需要注意默認(rèn)的時(shí)間格式,可以通過(guò)java代碼進(jìn)行修改。

1、規(guī)則文件編寫

package rules
import java.text.SimpleDateFormat
import java.util.Date

// 規(guī)則一:輸出當(dāng)前時(shí)間
rule "date_effective_rule_1"
    when
    then
        System.out.println("當(dāng)前時(shí)間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end

// 規(guī)則二: 該規(guī)則會(huì)在2022-05-18 10:54:26之后被激活
rule "date_effective_rule_2"
    date-effective "2022-05-18 10:54:26"
    when
    then
        System.out.println("date_effective_rule_2執(zhí)行了,規(guī)則允許被執(zhí)行的時(shí)間應(yīng)該在2022-05-18 10:54:26之后");
end

// 規(guī)則三: 該規(guī)則會(huì)在2023-05-18 10:54:26之后被激活
rule "date_effective_rule_3"
    date-effective "2023-05-18 10:54:26"
    when
    then
        System.out.println("date_effective_rule_3會(huì)在時(shí)間到了2023-05-18 10:54:26才激活");
end

規(guī)則一:輸出當(dāng)前時(shí)間
規(guī)則二: 該規(guī)則會(huì)在2022-05-18 10:54:26之后被激活
規(guī)則三: 該規(guī)則會(huì)在2023-05-18 10:54:26之后被激活

2、java代碼編寫

/**
 * 測(cè)試規(guī)則在執(zhí)行的時(shí)間之后才能執(zhí)行
 */
public class DroolsDateEffectiveApplication {
    public static void main(String[] args) {
        // 設(shè)置日期格式,否則可能會(huì)報(bào)錯(cuò)(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配規(guī)則名稱是已 date_effective_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("date_effective_"));
        kieSession.dispose();
    }
}

需要注意System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");這句,這個(gè)修改drools中的日期格式,因?yàn)橐?guī)則中寫的日期格式為date-effective "2023-05-18 10:54:26"而默認(rèn)的格式為d-MMM-yyyy,不修會(huì)報(bào)錯(cuò)。

3、運(yùn)行結(jié)果

當(dāng)前時(shí)間:2022-05-18 10:59:38
date_effective_rule_2執(zhí)行了,規(guī)則允許被執(zhí)行的時(shí)間應(yīng)該在2022-05-18 10:54:26之后

可以看到規(guī)則二執(zhí)行了,規(guī)則三沒(méi)有執(zhí)行,因?yàn)橐?guī)則三需要時(shí)間到達(dá)了2023-05-18 10:54:26才執(zhí)行,而當(dāng)前時(shí)間不符合。

4、注意事項(xiàng)

如果出現(xiàn)了Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]]這個(gè)錯(cuò)誤該怎么解決了,這是因?yàn)槿掌诟袷讲徽_。需要在java代碼中進(jìn)行如下設(shè)置System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss")

4、date-expires

定義規(guī)則的過(guò)期時(shí)間,即規(guī)則到了該時(shí)間之后就不可使用了。和date-effective的用法類似,此處就不演示了。

5、no-loop

定義當(dāng)當(dāng)前規(guī)則的結(jié)果修改了fact對(duì)象時(shí),是否可以再次執(zhí)行該規(guī)則。可以防止死循環(huán)

1、規(guī)則文件編寫

package rules
import java.util.concurrent.TimeUnit
import java.text.SimpleDateFormat
import java.util.Date

rule "no_loop_rule_1"
    no-loop true
    when
        $i: Integer(intValue() < 20)
    then
        modify($i){
        }
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_1 i=" + $i);
end

rule "no_loop_rule_2"
    no-loop false

    when
        $i: Integer(intValue() < 20)
    then
        modify($i){
        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_2 i=" + $i);
end

解釋:
no_loop_rule_1no-loop true表示如果當(dāng)前規(guī)則的RHS部分,對(duì)Fact對(duì)象進(jìn)行了修改,則不會(huì)再次觸發(fā)該規(guī)則。那如果是no_loop_rule_2修改了,會(huì)導(dǎo)致該規(guī)則的觸發(fā)嗎?答案是會(huì)觸發(fā),如果我不想被觸發(fā)呢?那么使用lock-on-active可以實(shí)現(xiàn)。
no_loop_rule_2no-loop false表示如果當(dāng)前規(guī)則的RHS部分,對(duì)Fact對(duì)象進(jìn)行了修改,那么還會(huì)再次匹配這個(gè)規(guī)則。

2、java代碼編寫

/**
 * 測(cè)試規(guī)則是否可以再次被執(zhí)行
 */
public class DroolsNoLoopApplication {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        kieSession.insert(10);
        // 只匹配規(guī)則名稱是已 no_loop_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("no_loop_"));
        // 睡眠5s,使規(guī)則文件中的規(guī)則執(zhí)行完
        TimeUnit.SECONDS.sleep(5);
        kieSession.dispose();
    }
}

此處 java 代碼,睡眠了5s,是為了讓規(guī)則執(zhí)行。

3、運(yùn)行結(jié)果

2022-05-18 11:42:29 no_loop_rule_1 i=10
2022-05-18 11:42:31 no_loop_rule_2 i=10
2022-05-18 11:42:31 no_loop_rule_1 i=10
2022-05-18 11:42:32 no_loop_rule_2 i=10

解釋:
2022-05-18 11:42:29 no_loop_rule_1 i=10: no_loop_rule_1被觸發(fā),由于RHS部分使用了modify修改了規(guī)則內(nèi)存中的對(duì)象,但是該規(guī)則存在 no-loop true 的屬性,所以該規(guī)則沒(méi)有再次被觸發(fā),即只輸出了一次。

2022-05-18 11:42:30 no_loop_rule_2 i=10 2022-05-18 11:42:30 no_loop_rule_1 i=10 此時(shí)規(guī)則 no_loop_rule_2 執(zhí)行了,由于該規(guī)則的 no-loop 為 false 并且使用了 modify 方法,所以該規(guī)則多次被觸發(fā)了,從結(jié)果上看,貌似規(guī)則 no_loop_rule_1 又再次被觸發(fā)了,不是應(yīng)該不被觸發(fā)嗎,因?yàn)樵O(shè)置了no-loop true?因?yàn)檫@是no_loop_rule_2導(dǎo)致no_loop_rule_1觸發(fā)的,而no_loop只對(duì)自身的RHS修改有效。

疑問(wèn):
那如果將 no-loop換成lock-on-active結(jié)果會(huì)一樣嗎?可以自己嘗試一下看看結(jié)果。

6、agenda-group

將被模式匹配成功后的規(guī)則,進(jìn)行分組,只有獲得焦點(diǎn)的組,才可以執(zhí)行規(guī)則。但是這個(gè)里面有個(gè)特列,如果某個(gè)規(guī)則在模式匹配,匹配成功了,但是沒(méi)有配置agenda-group,那么它會(huì)被分配到main組,這個(gè)main組的規(guī)則總是執(zhí)行的。

agenda-group的數(shù)據(jù)結(jié)構(gòu)就類似stack,激活的組是在棧頂。參考如下圖:

agenda-groups.jpg

參考鏈接: https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools

1、規(guī)則文件編寫

package rules

/**
    agenda-group 的數(shù)據(jù)結(jié)構(gòu)類似與棧,激活的組會(huì)被放置在棧頂,
    `main`是默認(rèn)組,總是存在的,即沒(méi)有配置agenda-group的就是`main`,
    `main`總是會(huì)執(zhí)行的。
*/

rule "agenda_group_001_rule_1"
    agenda-group "group-001"
    when
    then
        System.out.println("agenda_group_001_rule_1");
end

rule "agenda_group_001_rule_2"
    agenda-group "group-001"
    when
    then
        System.out.println("agenda_group_001_rule_2");
end

rule "agenda_group_002_rule_3"
    agenda-group "group-002"
    when
    then
        System.out.println("agenda_group_002_rule_3");
end

rule "agenda_group_no_group_rule_4"
    when
    then
        System.out.println("agenda_group_no_group_rule_4");
end

注意: 此處其實(shí)是 存在 3個(gè)組的,agenda_group_no_group_rule_4如果模式匹配成功后會(huì)被分配到main組,main總是會(huì)被執(zhí)行的。

2、java代碼編寫

/**
 * 測(cè)試規(guī)則分組
 */
public class DroolsAgendaGroupApplication {
    public static void main(String[] args) {
        // 設(shè)置日期格式,否則可能會(huì)報(bào)錯(cuò)(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
    
        // 激活組
        kieSession.getAgenda().getAgendaGroup("group-001").setFocus();

        // 只匹配規(guī)則名稱是已 agenda_group_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("agenda_group_"));
        kieSession.dispose();
    }
}

激活group-001分組。

3、運(yùn)行結(jié)果

agenda_group_001_rule_1
agenda_group_001_rule_2
agenda_group_no_group_rule_4

解釋:
agenda_group_no_group_rule_4為什么會(huì)被輸出呢?它沒(méi)有定義agenda-group啊,而且我們激活的也是group-001分組,它不應(yīng)該輸出啊。這是應(yīng)為這個(gè)規(guī)則模式匹配成功后被分配到了默認(rèn)的main組,而main組一定會(huì)被執(zhí)行的。

7、auto-focus

設(shè)置某個(gè)agenda-group默認(rèn)獲取到焦點(diǎn),和在java代碼中使用kieSession.getAgenda().getAgendaGroup("group-001").setFocus();或在drl文件中使用drools.setFocus(..)一樣。

8、activation-group

處于該分組中激活的規(guī)則,同一個(gè)組下,只有一個(gè)規(guī)則可以執(zhí)行,其余的會(huì)被取消執(zhí)行。但是別的組中激活的規(guī)則還是可以執(zhí)行的。

1、規(guī)則文件編寫

package rules

rule "activation_group_001_rule_1"
    activation-group "group-001"
    salience 1
    when
    then
        System.out.println("activation_group_001_rule_1");
end

rule "activation_group_001_rule_2"
    activation-group "group-001"
    salience 2
    when
    then
        System.out.println("activation_group_001_rule_2");
end

rule "activation_group_002_rule_3"
    activation-group "group-002"
    when
    then
        System.out.println("activation_group_002_rule_3");
end

rule "activation_group_no_group_rule_4"
    when
    then
        System.out.println("activation_group_no_group_rule_4");
end

activation-group "group-001"此處對(duì)這個(gè)組的規(guī)則指定了優(yōu)先級(jí),優(yōu)先級(jí)高的先執(zhí)行,執(zhí)行完之后,該組別的規(guī)則不執(zhí)行。

2、java代碼編寫

public class DroolsActivationGroupApplication {
    public static void main(String[] args) {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配規(guī)則名稱是已 activation_group_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("activation_group_"));
        kieSession.dispose();
    }
}

3、運(yùn)行結(jié)果

activation_group_001_rule_2
activation_group_002_rule_3
activation_group_no_group_rule_4

可以看到分組group-001中有2個(gè)規(guī)則,但是只執(zhí)行了一個(gè)規(guī)則。

9、duration

long類型的值,單位毫秒,如果在這個(gè)時(shí)間之后規(guī)則還成立,那么執(zhí)行該規(guī)則。

1、規(guī)則文件編寫

package rules
import java.text.SimpleDateFormat
import java.util.Date

rule "duration_rule_1"
    // 延遲1s后執(zhí)行規(guī)則
    duration 1000
    when
        $i: Integer(intValue() < 10)
    then
        System.out.println(Thread.currentThread().getName() + ": " + 
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+ 
        " duration_rule_1 $i:"+$i);
end

定義規(guī)則延遲1s后進(jìn)行執(zhí)行。

2、java代碼編寫

/**
 * 在多少毫秒后,如果條件還成立,則觸發(fā)該規(guī)則
 */
public class DroolsDurationApplication {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");

        FactHandle factHandle = kieSession.insert(3);
        // 只匹配規(guī)則名稱是已 duration_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        new Thread(() -> {
            // 調(diào)用此方法會(huì)阻塞調(diào)用線程,直到 `kieSession.halt();`的調(diào)用
            System.out.println("當(dāng)前時(shí)間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            kieSession.fireUntilHalt(new RuleNameStartsWithAgendaFilter("duration_"));
        }, "fire-thread").start();

        // 如果修改這個(gè)值,使得規(guī)則的條件不成立,看規(guī)則是否還執(zhí)行
        kieSession.update(factHandle, 4);

        TimeUnit.SECONDS.sleep(2);
        kieSession.halt();

        kieSession.dispose();
    }
}

注意:
1、我們調(diào)用出發(fā)所有規(guī)則執(zhí)行的方法不在是fireAllRules而是fireUntilHalt。
2、fireUntilHalt的調(diào)用會(huì)阻塞線程,直到調(diào)用halt方法,因此fireUntilHalt需要放置到另外的線程中調(diào)用。而且我們觀察規(guī)則的執(zhí)行,也是在這個(gè)線程中調(diào)用的。

3、運(yùn)行結(jié)果

當(dāng)前時(shí)間:2022-05-18 14:13:36
fire-thread: 2022-05-18 14:13:37 duration_rule_1 $i:4

可以看到,延遲1s后規(guī)則執(zhí)行了。

4、疑問(wèn)

如果我們?cè)?code>1s鐘之內(nèi),將規(guī)則的條件修改成不成立,那么規(guī)則還執(zhí)行嗎?答案:不執(zhí)行。

10、lock-on-active

rule flow groups or agenda groups配合使用。

需求:
我們有2個(gè)規(guī)則,并且同屬于一個(gè)組,規(guī)則二執(zhí)行完之后,工作內(nèi)存中的Fact對(duì)象的值發(fā)生了變化,導(dǎo)致規(guī)則一滿足執(zhí)行的條件,而規(guī)則一已經(jīng)執(zhí)行一遍了,此處需要阻止規(guī)則二的觸發(fā)導(dǎo)致規(guī)則一的出觸發(fā)。使用lock-on-active 即可實(shí)現(xiàn)。

1、規(guī)則文件編寫

package rules

import com.huan.drools.lockonactive.Person

rule "lock_on_active_rule_01"
    agenda-group "group-001"
    lock-on-active true
    when
        $p: Person(age < 18)
    then
        System.out.println("lock_on_active_rule_01: 用戶:[" + $p.getName() + "]當(dāng)前的年齡是:[" + $p.getAge() + "]");
 end

rule "lock_on_active_rule_02"
    agenda-group "group-001"
    when
        $p: Person(name == "張三")
    then
        modify($p){
            setAge(15)
        }
        System.out.println("lock_on_active_rule_02: 用戶:[" + $p.getName() + "]當(dāng)前的年齡是:[" + $p.getAge() + "]");
end

規(guī)則lock_on_active_rule_01加了lock-on-active true屬性后,規(guī)則lock_on_active_rule_02修改Fact導(dǎo)致規(guī)則lock_on_active_rule_01的條件成立,此時(shí)規(guī)則也是不會(huì)執(zhí)行的。

2、java代碼編寫

/**
 * 一個(gè)簡(jiǎn)單的實(shí)體類
 *
 * @author huan.fu
 * @date 2022/5/18 - 14:34
 */
@Getter
@Setter
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
}

public class DroolsLockOnActiveApplication {
    public static void main(String[] args) {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 激活組
        kieSession.getAgenda().getAgendaGroup("group-001").setFocus();

        Person person = new Person("張三", 20);
        kieSession.insert(person);

        // 只匹配規(guī)則名稱是已 lock_on_active_ 開(kāi)頭的規(guī)則,忽略其余的規(guī)則
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("lock_on_active_"));
        kieSession.dispose();
    }
}

3、運(yùn)行結(jié)果

lock_on_active_rule_02: 用戶:[張三]當(dāng)前的年齡是:[15]

可以看到只有規(guī)則二執(zhí)行了,說(shuō)明阻止了規(guī)則一的執(zhí)行。

四、完整代碼

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-rule-attributes

五、參考鏈接

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#rules-attributes-ref_drl-rules
2、 https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述(Overview) 以.drl為擴(kuò)展名的文件,是Drools中的規(guī)則文件,規(guī)則文件的編寫,遵循Drools規(guī)...
    老羊_肖恩閱讀 42,317評(píng)論 4 31
  • 對(duì)于Drools Rule的理解 一個(gè)規(guī)則可以包含三個(gè)部分: 屬性部分:定義當(dāng)前規(guī)則執(zhí)行的一些屬性等,比如是否可被...
    RyanLee_閱讀 6,973評(píng)論 0 8
  • Drools規(guī)則文件——語(yǔ)法屬性 salience 功能:設(shè)置規(guī)制執(zhí)行的優(yōu)先級(jí)值:數(shù)字(數(shù)字越大執(zhí)行優(yōu)先級(jí)越高)...
    天堂的碼頭閱讀 3,302評(píng)論 0 2
  • Drools是一款基于Java的開(kāi)源規(guī)則引擎 實(shí)現(xiàn)了將業(yè)務(wù)決策從應(yīng)用程序中分離出來(lái)。 優(yōu)點(diǎn): 1、簡(jiǎn)化系統(tǒng)架構(gòu),優(yōu)...
    生活的探路者閱讀 11,211評(píng)論 0 5
  • 深入了解Drools 簡(jiǎn)單介紹 筆者正在做風(fēng)控系統(tǒng),風(fēng)控系統(tǒng)里邊存在非常多的規(guī)則(比如:age < 16 || a...
    duval閱讀 22,601評(píng)論 2 19

友情鏈接更多精彩內(nèi)容