drools執行指定的規則

huan1993發表於2022-06-01

1、背景

在我們編寫drools規則檔案的過程中,可能會編寫好多規則。drools引擎在模式匹配的時候,可能一下子啟用了好多規則,但是我只想執行某個指定的規則,那麼這個時候該怎麼操作呢?

2、方案

2.1 通過AgendaFilter來實現

我們知道,在drools模式匹配的時候,會將所有的規則進行匹配,匹配成功的規則會放入到Agenda(議程)中,而fireAllRules(AgendaFilter)方法,可以傳遞一個AgendaFilterAgenda中的啟用的規則進行過濾。

2.2 通過entry-point來實現

使用entry-point可以定義模式的資料來源對應的入口點或事件流。這個不能完全實現,只是提供一個思路。

舉個例子:

Api(api == "/users/info" ) from entry-point "first-entry-point"
Api api = new Api("/users/info", 100);
EntryPoint entryPoint = kieSession.getEntryPoint("second-entry-point");
entryPoint.insert(api);
kieSession.fireAllRules();

上面這個例子,雖然工作記憶體中存在Api這個物件,但是由於 規則中的 entry-point和java程式碼中的entry-point不一致,規則是沒有匹配成功的。

3、實現

此處我們通過 AgendaFilter來實現具體呼叫某個具體的規則。

3.1 需求

我們存在一個Api(api,invokedCnt)物件

規則一:工作記憶體中存在Api物件,且屬性api=="/users/info"
規則二:工作記憶體中存在Api物件,且屬性invokedCnt > 10

我們向工作記憶體中插入一個 Api("/users/info",100),此時規則一和規則二都會匹配到,但是我只想執行規則二。

3.2 drl 檔案編寫

package rules

import com.huan.drools.Api

rule "rule_agenda_filter_01"
    when
        $api: Api(api == "/users/info" )
    then
        System.out.println("當前執行的規則是: " + drools.getRule().getName());
end

rule "rule_agenda_filter_02"
    when
        $api: Api(invokedCnt > 10)
    then
        System.out.println("當前執行的規則是: " + drools.getRule().getName());
end

3.3 部分java程式碼

Api api = new Api("/users/info", 100);
kieSession.insert(api);

// 所有模式匹配成功後的規則回進入到agenda中,然後通過AgendaFilter過濾出需要執行的規則
kieSession.fireAllRules(new AgendaFilter() {
    @Override
    public boolean accept(Match match) {
        String ruleName = match.getRule().getName();
        return Objects.equals(ruleName, "rule_agenda_filter_02");
    }
});

可以看到此處通過AgendaFilter進行了規則的過濾,只執行rule_agenda_filter_02規則。

注意: 此處雖然是一個過濾,但是並不意味著只有rule_agenda_filter_02規則是啟用的,而是所有滿足條件的規則都是啟用的。

3.4 執行結果

當前執行的規則是: rule_agenda_filter_02

可以看到實現了我們想要的結果。

4、完整程式碼

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-invoked-specify-rule

相關文章