在使用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来进行加载。这样,相互之间就不会产生影响了。



Drools规则引擎使用AgendaFilter触发指定规则会校验所有规则插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.choupangxia.com/2021/12/28/drools-agenda-filter/