You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅向Drools决策表的ACTION区域传递对象?

解决Drools决策表中优雅引用输出对象的问题

我明白你现在的困扰——用Drools决策表时,想通过只读输入对象和可变输出对象分离规则的输入输出,但目前只能用虚拟条件列的hack来让ACTION区识别输出对象,确实不够优雅。下面我给你几个更规范的解决方案,帮你摆脱这个窘境:

方案1:在CONDITION区域明确匹配输出对象

这是最符合Drools规则设计思路的方式,你不需要虚拟条件列,只需要在CONDITION区添加一行来匹配工作内存中的输出对象即可:

假设你的决策表结构如下(简化版):

CONDITIONACTION
$input: RuleInput()// 基于$input的规则逻辑
$output: RuleOutput()$output.setPrice(...)

这样在CONDITION区的第二行,我们明确声明并匹配了工作内存中的RuleOutput对象,给它起了别名$output,之后在ACTION区就能直接使用这个变量了,完全不需要虚拟条件。

你之前尝试把输入和输出放在同一单元格报错,是因为Drools决策表的CONDITION单元格中,每个对象模式需要单独一行(或格式正确的分号分隔),分开两行声明是最清晰且不易出错的方式。

方案2:使用全局变量(Global)传递输出对象

如果你的输出对象是全局共享的(比如所有规则都要修改同一个输出对象),可以把它设置为Drools的全局变量,这样不需要在CONDITION区匹配,直接在ACTION区引用:

第一步:修改Kotlin代码,设置全局变量

private fun calculatePrice(input: RuleInput, path: String): RuleOutput {
    val kieRepository: KieRepository = kieServices.repository
    kieRepository.addKieModule { kieRepository.defaultReleaseId }
    val kb: KieBuilder = kieServices.newKieBuilder(prepareFileSystem(kieServices, path))
    kb.buildAll()
    val kieModule: KieModule = kb.kieModule
    val kieContainer: KieContainer = kieServices.newKieContainer(kieModule.releaseId)
    val output = RuleOutput()
    kieContainer.newKieSession().apply {
        setGlobal("ruleOutput", output) // 将输出对象设为全局变量
        insert(input)
        fireAllRules()
    }
    return output
}

第二步:在决策表中声明并使用全局变量

你需要在决策表的RuleSet区域(或者对应的DRL文件开头)添加全局变量的声明:

global com.yourpackage.RuleOutput ruleOutput;

之后在ACTION区就可以直接使用这个全局变量了:

ruleOutput.setDiscount(0.8)

为什么你之前的方式会报错?

你提到在ACTION区直接用$output会提示无法解析,核心原因是:Drools规则中的变量必须先在CONDITION区通过模式匹配声明,或者通过全局变量定义,否则规则引擎无法识别这个变量的存在。而你之前的虚拟条件列本质上是通过一个恒真的条件(比如1==1)偷偷声明了$output变量,虽然能工作,但属于不规范的hack。

推荐方案

如果你的输出对象是和输入对象一一对应的(每个输入对应一个输出),优先选择方案1,因为它更符合Drools的规则匹配逻辑,代码可读性更高;如果是多个规则共享同一个全局输出对象,方案2会更简洁。

内容的提问来源于stack exchange,提问作者ar811

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 17:07:32