Drools从声明变量获取List对象时规则不执行问题咨询
问题原因及解决方案
核心问题:对from操作符的行为误解
你遇到的规则不触发问题,根源是没搞清楚Drools中from操作符的实际作用:当你写$class_var: List() from $object_with_var.getListVar()时,Drools会把getListVar()返回的集合逐个拆成单个元素,然后检查每个元素是否是List类型。但你的listVar里存的是普通Object(不是List实例),自然没有元素能匹配List()的条件,规则也就不会触发。
而你能生效的写法Foo(listVar != null , !listVar.isEmpty()),是直接在Foo对象的属性约束里判断列表本身的状态,没有涉及集合元素的遍历,所以能正确匹配到符合条件的Foo实例。
正确的写法示例
如果需要绑定listVar到变量同时触发规则,推荐直接在Foo的模式里完成,这也是Drools的最佳实践:
rule "Match Foo with non-empty list and bind the list variable" when $object_with_var: Foo( listVar != null, !listVar.isEmpty(), $class_var = listVar ) then print("Rule fired! List content: " + $class_var); end
如果一定要用from来匹配列表对象本身(不推荐,写法冗余),可以通过eval强制匹配对象引用:
rule "Bind list object using eval" when $object_with_var: Foo() $class_var: List() eval( $class_var == $object_with_var.getListVar() && !$class_var.isEmpty() ) then print("Rule fired!"); end
补充说明
from操作符的设计初衷是遍历集合元素,比如你想匹配列表中的某个特定类型元素时才会用到,例如:
rule "Match String elements in the list" when Foo(listVar != null) $str: String() from $object_with_var.getListVar() then print("Found string element: " + $str); end
这种场景下,列表里的每个String元素都会触发一次规则。而你的需求是匹配Foo对象且其列表非空,直接在Foo的模式约束里处理是最简洁高效的方式。
内容的提问来源于stack exchange,提问作者miguelsuri
相关产品推荐
相关产品推荐

