Drools怎么集成?

wen python案例 4

本文目录导读:

Drools怎么集成?

  1. 传统 Spring Boot 项目集成(最推荐,最常用)
  2. 使用 kie-spring 自动配置(注解方式,更简洁)
  3. 传统 Java 项目(非 Spring 环境)
  4. 使用 Drools Workbench + KIE Server(分布式/微服务架构)
  5. 关键注意事项与最佳实践
  6. 总结推荐路线

Drools 是一个基于 Java 的规则引擎,常用于业务规则管理(BRMS),集成 Drools 通常有几种主流方式,具体取决于你的项目架构(传统 Java 项目、Spring Boot 项目或微服务架构)。

以下是几种常见的集成方案:

传统 Spring Boot 项目集成(最推荐,最常用)

这是目前最主流的集成方式,利用 Spring 的依赖注入管理 KieContainer、KieSession 等核心组件。

步骤:

(1)添加 Maven 依赖

pom.xml 中添加 Drools 核心包和 Spring 集成包:

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.73.0.Final</version> <!-- 或 8.x 等较新版 -->
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.73.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-mvel</artifactId> <!-- 或 drools-ecj,用于规则编译 -->
    <version>7.73.0.Final</version>
</dependency>
<!-- 如果是 Spring Boot 项目,可以使用 kie-spring -->
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>7.73.0.Final</version>
</dependency>

(2)配置规则文件路径

.drl 规则文件放在 src/main/resources/rules/ 目录下。

(3)创建 KieContainer 配置类

import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DroolsConfig {
    private static final String RULES_PATH = "rules/";
    @Bean
    public KieContainer kieContainer() {
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        // 读取 resources 下的所有 .drl 文件
        // 这里可以写死,也可以动态扫描
        kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + "rule1.drl"));
        kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + "rule2.drl"));
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll(); // 编译规则
        KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieBuilder.getKieModule());
        KieContainer kieContainer = kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
        return kieContainer;
    }
    @Bean
    public KieSession kieSession(KieContainer kieContainer) {
        // 通常不直接暴露单例 session(不是线程安全的),这里只是演示
        // 实际使用中建议在每次调用时创建新的无状态 session,或者使用有状态 session 并管理锁
        return kieContainer.newKieSession();
    }
}

(4)在 Service 中调用规则引擎

import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RuleService {
    @Autowired
    private KieContainer kieContainer;
    public void executeRules(Object fact) {
        // 每次都创建新的 session,避免线程安全问题
        KieSession kieSession = kieContainer.newKieSession();
        try {
            kieSession.insert(fact);      // 插入事实对象
            kieSession.fireAllRules();    // 触发规则
        } finally {
            kieSession.dispose();         // 必须释放资源
        }
    }
    // 如果是无状态规则,可以使用 StatelessKieSession
    // public void executeStateless(Object fact) {
    //     StatelessKieSession statelessKieSession = kieContainer.newStatelessKieSession();
    //     statelessKieSession.execute(fact);
    // }
}

使用 kie-spring 自动配置(注解方式,更简洁)

如果你不想手动创建 KieContainer,可以使用 kie-spring 提供的注解。

步骤:

(1)定义规则文件

同上,放在 classpath:rules/ 下。

(2)配置 kie-spring 命名空间

在 Spring 的 XML 配置(如果使用 XML)或通过 @ImportResource 引入,如果使用纯注解,可以配置一个扫描器:

import org.kie.spring.annotations.KieModule;
import org.kie.spring.annotations.KieReleaseId;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class KieConfig {
    @Bean
    @KieModule
    public KieServices kieServices() {
        return KieServices.Factory.get();
    }
    // 或者使用 @KieContainer 注解(需要引入 kie-spring 的自动配置)
}

kie-spring 在 Spring Boot 中自动配置能力有限,很多项目依然选择手动构建 KieContainer,或者使用 Drools 的 kmodule.xml 配置文件。

传统 Java 项目(非 Spring 环境)

不依赖 Spring,直接使用 Drools API:

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class DroolsDemo {
    public static void main(String[] args) {
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer(); // 自动读取 META-INF/kmodule.xml 和 resources 下的 rule
        KieSession kieSession = kieContainer.newKieSession("ksession-rules"); // 名称对应 kmodule.xml 中的配置
        Object fact = new YourFactObject();
        kieSession.insert(fact);
        kieSession.fireAllRules();
        kieSession.dispose();
    }
}

对应的 kmodule.xml(放在 src/main/resources/META-INF/ 下):

<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <kbase name="rulesKB" packages="rules">
        <ksession name="ksession-rules" type="stateful" />
    </kbase>
</kmodule>

使用 Drools Workbench + KIE Server(分布式/微服务架构)

如果规则需要频繁修改、给业务人员使用,或者系统是微服务架构,推荐使用 KIE Server

  • Drools Workbench:Web 界面,业务人员可以编写、测试规则(有引导式规则)。
  • KIE Server:提供 REST 或 JMS API,你的 Java 应用作为客户端远程调用执行规则。

企业级集成步骤:

  1. 部署 Drools Workbench(通常是一个 WAR 包或容器化镜像)。
  2. 在 Workbench 中创建项目、编写规则,并发布(Deploy)。
  3. 你的 Java 应用引入 kie-server-client 依赖:
<dependency>
    <groupId>org.kie.server</groupId>
    <artifactId>kie-server-client</artifactId>
    <version>7.73.0.Final</version>
</dependency>

通过 REST 客户端调用执行规则:

import org.kie.server.client.KieServicesClient;
import org.kie.server.client.KieServicesFactory;
import org.kie.server.client.RuleServicesClient;
String serverUrl = "http://localhost:8080/kie-server/services/rest/server";
String userName = "kieserver";
String password = "kieserver1!";
KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(serverUrl, userName, password);
KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
RuleServicesClient ruleClient = client.getServicesClient(RuleServicesClient.class);
// 执行规则
ServiceResponse response = ruleClient.executeCommands("containerId", (ExecutionResults results) -> {
    // 插入事实并执行
    return results;
});

关键注意事项与最佳实践

  1. 线程安全KieSession线程不安全的,不要把它作为单例 Bean,要么每次调用时新建(推荐),要么使用 StatelessKieSession(线程安全)。
  2. 性能优化
    • 使用 StatelessKieSession 如果不需要积累多个事实或工作内存状态。
    • 缓存 KieContainer(它是线程安全的),每次执行时只创建新的 KieSession
    • 避免在热路径(如高频循环)中频繁创建 KieContainer,它只应在启动时或规则热加载时重建。
  3. 动态规则加载:如果规则需要运行时修改,不要重启应用,可以通过监听文件变化或数据库规则活页夹(如 Drools 的 ResourceChangeScanner 或自己实现轮询)重新生成 KieContainer;或使用 KIE Server,修改规则后重新部署(热部署)。
  4. 规则文件组织:不要把所有规则写在一个超大 .drl 文件中,建议按业务模块拆分(如 discount.drlfraud.drl),使用规则包(package)进行隔离。

总结推荐路线

  • 中小型项目、规则相对固定、修改不频繁:使用方式 1 (Spring Boot + 手动构建 KieContainer),简单可靠。
  • 微服务架构、规则需要热更新、业务人员需要界面编辑:使用方式 4 (KIE Server + Workbench),真正的企业级 BRMS 方案。
  • 纯轻量级、无需 Spring:使用方式 3 (传统 Java + kmodule.xml)

抱歉,评论功能暂时关闭!