Drools:如何在not表达式内实现短路与(&&)条件?
在Drools的not表达式中实现短路与逻辑
我懂你的困扰——在not表达式里,Drools引擎没按你预期的短路逻辑执行,导致非double类型的数据也调用了getValue()方法,最后因为类型不匹配报错。这是因为Drools处理模式约束时,会做内部优化,不一定严格按照你写的顺序执行,所以哪怕name不匹配,getValue()还是可能被提前调用。
要解决这个问题,我们可以通过拆分模式的方式,强制先过滤出符合name条件的实例,再对这些实例做getValue()和时间条件的判断,以此实现类似短路与的效果。
修改后的规则代码
rule "data value > 50 for 10 seconds" dialect "java" when // 先匹配double类型且value>50的数据 data: MyData(name.contains("double"), getValue() > 50) from entry-point "dataEntryPoint" // 在not中拆分逻辑,先筛选同name的实例,再判断后续条件 not( // 第一步:仅保留和当前data同name的记录,完全不涉及getValue() $candidate: MyData(name == data.name) from entry-point "dataEntryPoint" // 第二步:只对筛选后的实例,判断value<50且在时间范围内 MyData( this == $candidate, getValue() < 50, this after[0, 10s] data ) ) then doSmthg(); end
为什么这样能解决问题?
- 第一个子模式
$candidate: MyData(name == data.name)会先从入口点筛选出所有name匹配的MyData实例,这一步完全不会调用getValue()。 - 只有通过第一步筛选的实例,才会进入第二个子模式执行后续判断,彻底避免了非double类型的数据触发
getValue()方法。
更简洁的替代写法
如果你追求代码简洁,也可以在not的模式中把name约束放在最前面,利用Drools的约束优先级(字段约束优先于方法调用约束)来实现短路效果:
rule "data value > 50 for 10 seconds" dialect "java" when data: MyData(name.contains("double"), getValue() > 50) from entry-point "dataEntryPoint" not( MyData( name == data.name, // 字段约束优先执行 getValue() < 50, // 只有name匹配才会执行这个方法调用 this after[0, 10s] data ) from entry-point "dataEntryPoint" ) then doSmthg(); end
这种写法的核心是Drools会优先处理字段匹配类的约束,再处理方法调用类的约束,也能达到短路效果,但拆分模式的写法更直观,可读性更强,也不容易因为引擎优化出现意外。
内容的提问来源于stack exchange,提问作者bjalexmdd
相关产品推荐
相关产品推荐

