应选用 drools 8.44.0.final 版本并排除冗余依赖,规则文件需置于 resources/rules/ 下且配置 kmodule.xml,kiesession 非线程安全须按场景管理生命周期,spring bean 需通过 fact 或 global 注入规则上下文。

用 Maven 引入 Drools 依赖时版本怎么选
别直接抄网上老教程的 7.10.0.Final 或更早版本——这些默认绑定旧版 Kie API,和 Java 11+、Spring Boot 2.6+ 冲突明显,启动就报 NoClassDefFoundError: org/kie/api/KieServices。实际项目建议锁死 8.44.0.Final(当前兼容 JDK 17、Spring Boot 3.2 的最稳版本),且必须显式排除传递依赖里的 kie-api 冗余包。
- 在
pom.xml中用<exclusions></exclusions>干掉org.kie:kie-api和org.drools:drools-core的重复引入 - 只保留
org.kie:kie-api和org.drools:drools-compiler两个核心依赖,其他如drools-templates按需加 - 如果用 Spring Boot,优先选
spring-boot-starter-drools(但注意它只到 Drools 8.39,得手动覆盖 bom)
规则文件(.drl)放哪、怎么被加载
Drools 不会自动扫描 classpath 下所有 .drl 文件——你得自己告诉它路径,否则 KieContainer 构建时规则全为空,运行时不报错也不生效,查半天才发现规则根本没加载。
- 推荐把
.drl放在src/main/resources/rules/下,避免和 Java 类混在一起 - 加载时用
KieServices.newKieClasspathContainer()会默认找src/main/resources/META-INF/kmodule.xml;没这个文件,规则就进不了容器 -
kmodule.xml必须声明<kbase></kbase>和<ksession></ksession>,哪怕只配一个默认 session,否则KieContainer.getKieSession()返回 null
Java 里调用规则时 KieSession 生命周期怎么管
很多人把 KieSession 当成工具类静态复用,结果多线程下规则触发混乱、fact 冲突、内存泄漏——KieSession 不是线程安全的,也不能长期 hold 住不 dispose。
- 短生命周期场景(如单次订单校验):每次 new
KieContainer→getKieSession()→ insert + fireAllRules →dispose() - 长生命周期场景(如风控实时引擎):用单例
KieContainer,但每个请求新建KieSession(调newKieSession()),用完不 dispose(由容器统一管理) - 千万别把
KieSession注入 Spring 容器并设为 singleton——Spring 不知道它内部状态,会出不可预知行为
规则中使用 Spring Bean 报空指针怎么办
Drools 默认规则上下文(KnowledgeHelper)看不到 Spring 管理的 bean,直接写 @Autowired 或 ctx.getBean(XxxService.class) 全是 null。这不是配置问题,是设计隔离导致的。
立即学习“Java免费学习笔记(深入)”;
- 正确做法:在 Java 调用侧把 service 封装进 fact,比如
session.insert(new RuleContext(xxxService)) - 规则里用
$ctx : RuleContext()匹配,再通过$ctx.getService().doSomething()调用 - 或者改用
Global:在 session 上 setGlobal("xxxService", xxxService),规则里声明global XxxService xxxService;——但 global 是全局共享,不能带请求上下文











