Spring Boot集成Drools:多Drl文件单KieContainer管理咨询
Spring Boot集成Drools多上下文规则隔离实现方案
核心结论
不需要为每个业务上下文创建独立的KieContainer,单个KieContainer即可实现不同上下文规则的隔离触发,以下是两种主流实现方式:
方式一:使用Agenda Group(议程组)隔离规则
这是最简单的实现方式,无需调整文件结构,仅需给规则标记所属的上下文组,执行时激活对应组即可。
步骤1:给DRL规则标记Agenda Group
修改每个上下文的.drl文件,为规则添加agenda-group属性:
// ctxt1.drl rule "Context1_Rule_01" agenda-group "ctxt1" // 指定所属上下文组 when RequestPOJO(contextType == "ctxt1") // 可结合业务条件进一步约束 then // 规则执行逻辑 end
// ctxt2.drl rule "Context2_Rule_01" agenda-group "ctxt2" when RequestPOJO(contextType == "ctxt2") then // 规则执行逻辑 end
步骤2:执行时激活目标上下文的Agenda Group
修改规则执行代码,通过设置焦点激活对应组的规则:
// 根据业务上下文获取对应的组名,示例从RequestPOJO中提取 String targetAgendaGroup = RequestPOJO.getContextType(); KieSession kieSession = kieContainer.newKieSession(); // 激活目标议程组,设置焦点后仅该组规则会被触发 kieSession.getAgenda().getAgendaGroup(targetAgendaGroup).setFocus(); kieSession.insert(RequestPOJO); kieSession.fireAllRules(); kieSession.dispose();
方式二:拆分KieBase实现物理隔离
如果业务上下文规则差异极大、数量较多,可通过KieBase拆分实现规则的物理隔离,每个KieBase仅包含对应上下文的规则。
步骤1:配置kmodule.xml
在src/main/resources/META-INF下创建kmodule.xml,定义多个KieBase和对应的KieSession:
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://www.drools.org/xsd/kmodule"> <!-- 上下文1的KieBase,仅包含ctxt1包下的规则 --> <kbase name="kbaseCtxt1" packages="ctxt1"> <ksession name="ksessionCtxt1"/> </kbase> <!-- 上下文2的KieBase,仅包含ctxt2包下的规则 --> <kbase name="kbaseCtxt2" packages="ctxt2"> <ksession name="ksessionCtxt2"/> </kbase> <!-- 上下文3的KieBase,仅包含ctxt3包下的规则 --> <kbase name="kbaseCtxt3" packages="ctxt3"> <ksession name="ksessionCtxt3"/> </kbase> </kmodule>
步骤2:调整DRL文件结构
将不同上下文的.drl文件放到对应包路径下:
src/main/resources/ ├── ctxt1/ │ └── ctxt1.drl ├── ctxt2/ │ └── ctxt2.drl ├── ctxt3/ │ └── ctxt3.drl └── META-INF/ └── kmodule.xml
步骤3:修改KieContainer Bean(手动构建场景)
如果是手动通过KieFileSystem构建KieContainer,需确保写入正确的资源路径:
@Bean public KieContainer getKieContainer() { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kieFileSystem = kieServices.newKieFileSystem(); // 写入kmodule.xml kieFileSystem.write("META-INF/kmodule.xml", ResourceFactory.newClassPathResource("META-INF/kmodule.xml")); // 写入各上下文的DRL文件到对应包路径 kieFileSystem.write("src/main/resources/ctxt1/ctxt1.drl", ResourceFactory.newClassPathResource("ctxt1/ctxt1.drl")); kieFileSystem.write("src/main/resources/ctxt2/ctxt2.drl", ResourceFactory.newClassPathResource("ctxt2/ctxt2.drl")); kieFileSystem.write("src/main/resources/ctxt3/ctxt3.drl", ResourceFactory.newClassPathResource("ctxt3/ctxt3.drl")); KieBuilder kb = kieServices.newKieBuilder(kieFileSystem); kb.buildAll(); KieModule kieModule = kb.getKieModule(); return kieServices.newKieContainer(kieModule.getReleaseId()); }
步骤4:获取对应上下文的KieSession执行规则
根据业务上下文,获取指定名称的KieSession:
// 根据业务上下文获取对应的KieSession名称 String targetKieSessionName = "ksession" + RequestPOJO.getContextType(); KieSession kieSession = kieContainer.newKieSession(targetKieSessionName); kieSession.insert(RequestPOJO); kieSession.fireAllRules(); kieSession.dispose();
两种方式对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Agenda Group | 配置简单、无需调整文件结构、切换灵活 | 规则同属一个KieBase,编译时统一处理 | 规则数量少、上下文切换频繁 |
| 拆分KieBase | 规则物理隔离、编译运行独立、性能更优 | 需配置kmodule.xml、调整文件结构 | 规则数量多、上下文差异大 |
内容的提问来源于stack exchange,提问作者mac
相关产品推荐
相关产品推荐

