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

如何为Drools Rule Units配置自定义*.drl文件路径?

为Drools Rule Units配置自定义DRL路径及多会话管理

核心思路

每个独立会话对应专属的KieContainer,通过KieFileSystem加载不同来源(S3、磁盘、内存)的DRL文件,再将Rule Unit与该KieContainer绑定,实现会话的独立启停与规则隔离。

步骤实现

1. 封装会话规则加载逻辑

为每个会话创建独立的KieContainer,步骤如下:

  • 初始化KieServices核心服务
  • 创建KieFileSystem,添加自定义来源的DRL资源
  • 构建KieModule并生成KieContainer

代码示例:

import org.kie.api.KieServices;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import java.nio.file.Path;
import java.io.InputStream;

// 会话规则加载工具类
public class SessionRuleLoader {
    public static KieContainer createKieContainerForSession(Object... drlResources) {
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();

        // 遍历添加不同来源的DRL资源
        for (Object resource : drlResources) {
            if (resource instanceof String) {
                // 内存中的DRL字符串
                kfs.write("src/main/resources/rules/in-memory-rule.drl", (String) resource);
            } else if (resource instanceof Path) {
                // 磁盘路径的DRL文件
                Path drlPath = (Path) resource;
                kfs.write("src/main/resources/rules/" + drlPath.getFileName(), 
                          kieServices.getResources().newFileSystemResource(drlPath));
            } else if (resource instanceof InputStream) {
                // S3等远程来源的输入流(需自行处理S3文件下载逻辑)
                InputStream drlStream = (InputStream) resource;
                kfs.write("src/main/resources/rules/s3-rule.drl", 
                          kieServices.getResources().newInputStreamResource(drlStream));
            }
        }

        // 构建KieModule并注册到仓库
        KieRepository kieRepository = kieServices.getRepository();
        ReleaseId releaseId = kieServices.newReleaseId("com.yourdomain", "session-rules", "1.0." + System.currentTimeMillis());
        kfs.generateAndWritePomXML(releaseId);
        KieModule kieModule = kieServices.newKieBuilder(kfs).buildAll().getKieModule();
        kieRepository.addKieModule(kieModule);

        // 返回专属KieContainer
        return kieServices.newKieContainer(releaseId);
    }
}

2. 绑定Rule Unit到会话的KieContainer

每个会话的Rule Unit实例基于专属KieContainer创建,实现规则隔离:

import org.kie.api.runtime.rule.RuleUnitInstance;
import org.kie.api.runtime.rule.RuleUnit;
import org.kie.api.runtime.rule.DataStream;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

// 自定义Rule Unit示例
public class MyRuleUnit implements RuleUnit {
    // 规则所需数据流(可定义多个)
    private DataStream<Order> orders;

    // 构造方法、getter/setter省略

    @Override
    public RuleUnitInstance createInstance() {
        return null;
    }
}

// 会话管理示例
public class SessionManager {
    // 存储会话ID与对应KieContainer的映射
    private Map<String, KieContainer> sessionContainers = new ConcurrentHashMap<>();

    // 创建会话并加载规则
    public String createSession(Object... drlResources) {
        String sessionId = UUID.randomUUID().toString();
        KieContainer kieContainer = SessionRuleLoader.createKieContainerForSession(drlResources);
        sessionContainers.put(sessionId, kieContainer);
        return sessionId;
    }

    // 启动会话的Rule Unit并处理数据
    public void startSession(String sessionId, DataStream<?>... dataStreams) {
        KieContainer kieContainer = sessionContainers.get(sessionId);
        if (kieContainer == null) {
            throw new IllegalArgumentException("Session not found: " + sessionId);
        }

        // 绑定数据流到Rule Unit
        MyRuleUnit ruleUnit = new MyRuleUnit();
        ruleUnit.setOrders((DataStream<Order>) dataStreams[0]);

        // 基于KieContainer创建RuleUnitInstance并执行
        RuleUnitInstance instance = kieContainer.newRuleUnitInstance(ruleUnit);
        instance.fire();
        // 若需持续处理数据流,可保留instance引用,后续调用fire()
    }

    // 停止会话并释放资源
    public void stopSession(String sessionId) {
        KieContainer kieContainer = sessionContainers.remove(sessionId);
        if (kieContainer != null) {
            kieContainer.dispose();
        }
    }
}

3. 关键注意事项

  • 资源路径规范:KieFileSystem.write()的第一个参数需符合src/main/resources/下的路径格式,Drools会自动识别该路径下的DRL文件。
  • 版本隔离:每个会话的ReleaseId需唯一(示例中用时间戳保证),避免不同会话的规则互相干扰。
  • 资源释放:停止会话时务必调用KieContainer.dispose(),释放内存与相关资源。
  • 远程资源处理:对于S3等远程来源,需自行实现文件下载逻辑,将文件转为InputStream后传入加载方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:45:12