Drools规则引擎使用AgendaFilter触发指定规则会校验所有规则
在使用Drools规则引擎时,你是否会遇到这样的情况:明明使用了AgendaFilter指定只触发某条规则,但Drools规则引擎却校验了所有的规则。
比如,在代码中使用方式如下:
int rulesFired = kSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule name 1"));
对应的DRL规则文件内容如下:
rule "test1" when $var : Map(this["key"] == "gold") then do something end rule "test2" when $var : Map(this["key"] == "gold" && this["other"] == "silver") then do something end
在执行上述代码时,虽然只触发了一条规则,但Drools仍然会校验,也就是会执行所有规则的条件判断,即when部分的代码逻辑。
有时还会收到其他名称不是AgendaFilter指定名称的规则的错误信息,因为在执行上述代码时,某些规则条件部分的变量并为通过kSession insert进去。
比如上述规则中,当执行test1时,传入的Map中只包含了“key”,这时由于Map中并未包含test2中的“other”,就会出现空指针异常。但通常情况下,我们是并不关心test2的,因为要执行的规则是test1。
问题解答
Drools在对规则进行评估时,会对所有规则进行评估计算。也就是说,会先匹配执行所有规则的when部分,然后选择符合条件的,再执行其中的then部分。
Drools为了减少整体工作量,会组合相同的条件或条件的一部分来进行评估,比如利用模式(pattern)或约束(constraint)。因此,在运行时中无法阻止指定规则的评估。
相关实现及说明可以参考Rete算法部分的文档说明。AgentFilter只影响规则触发的推理部分。
当然,上述问题并不是不可解决,你可以通过将规则文件放在不同的package下,然后通过不同的KieSession来进行加载。这样,相互之间就不会产生影响了。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2021/12/28/drools-agenda-filter/