1、背景
在我們編寫drools
規則檔案的過程中,可能會編寫好多規則。drools
引擎在模式匹配的時候,可能一下子啟用了好多規則,但是我只想執行某個指定的規則,那麼這個時候該怎麼操作呢?
2、方案
2.1 通過AgendaFilter來實現
我們知道,在drools
模式匹配的時候,會將所有的規則進行匹配,匹配成功的規則會放入到Agenda
(議程)中,而fireAllRules(AgendaFilter)
方法,可以傳遞一個AgendaFilter
對Agenda
中的啟用的規則進行過濾。
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