Drools规则中全局HashMap无法访问及条件匹配的问题解决
Drools规则中全局HashMap在when部分的正确使用方式
问题根源
你之前的写法san == aeRuleMap.get("1").isSan()存在两个核心问题:
- 直接链式调用未做空指针校验,一旦
aeRuleMap.get("1")返回null,立刻触发空指针异常; - Drools的when部分是声明式模式匹配,引擎需要跟踪工作内存中的对象状态,直接调用HashMap内部对象的方法,引擎无法识别对象变化,进而导致执行卡住。
正确实现方式
方式1:变量绑定+模式匹配(推荐)
先将HashMap中取出的对象绑定为规则变量,再调用方法并匹配事实属性,同时增加空检查避免异常:
rule "Validate San Attribute" // 声明全局变量(需和Java代码中设置的类型、名称一致) global java.util.HashMap aeRuleMap; when // 先从全局HashMap中取出key为"1"的对象,绑定为$ruleObj,同时检查对象非空 $ruleObj: Object() from aeRuleMap.get("1") // 调用对象的isSan()方法,绑定结果为$expectedSan $expectedSan: Boolean() from $ruleObj.isSan() // 匹配工作内存中的目标事实,校验其san属性与预期值一致 TargetFact(san == $expectedSan) then // 规则触发后的执行逻辑 System.out.println("San属性匹配成功,规则执行"); end
方式2:使用eval做条件判断(适合简单场景)
如果场景简单,也可以用eval包裹完整条件,但必须加上空指针校验:
rule "Check San Match" global java.util.HashMap aeRuleMap; when // 先匹配工作内存中的目标事实 $fact: TargetFact() // 用eval包裹条件,依次校验全局变量、取出的对象非空,再对比属性 eval( aeRuleMap != null && aeRuleMap.get("1") != null && $fact.getSan() == aeRuleMap.get("1").isSan() ) then // 执行逻辑 end
关键注意事项
- 确保全局HashMap中存储的对象实现了
Serializable接口,符合Drools对工作内存对象的要求; - 如果HashMap中的对象会动态修改,必须调用
kieSession.update($ruleObj)通知规则引擎对象状态变化,否则规则不会重新触发; - 尽量减少when部分的Java方法调用,优先用变量绑定+模式匹配的写法,既符合Drools的设计逻辑,也便于规则维护和调试。
内容的提问来源于stack exchange,提问作者Shanij P.S
相关产品推荐
相关产品推荐

