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

Drools Engine 8.43.0.Final中如何序列化KieBase

解决方案

针对KieBase不可序列化无法存入Redis,以及KieSession反序列化依赖KieBase的问题,提供以下几种可行方案:

1. 序列化KieBase的构建配置而非实例本身

KieBase的核心是规则集合和配置,与其序列化不可序列化的KieBase实例,不如持久化构建它的原始配置,取出时重新生成KieBase:

  • 步骤:
    • 收集构建KieBase所需的所有资源:将KieFileSystem中的.drl规则文件、决策表等资源转为字节数组或字符串;
    • 导出KieBase的配置:通过kieBase.getKieBaseConfiguration().toProperties()获取配置属性;
    • 将上述资源和配置打包成一个可序列化的POJO(比如KieBaseCacheEntry),存入Redis;
    • 从Redis取出时,通过KieServices重新加载资源、应用配置,重建KieBase:
      // 存入时的逻辑
      KieServices kieServices = KieServices.Factory.get();
      KieFileSystem kfs = kieServices.newKieFileSystem();
      // 假设已添加规则文件到kfs
      byte[] drlContent = kfs.read("src/main/resources/rules/myRules.drl");
      Properties kieBaseProps = kieServices.newKieBaseConfiguration().toProperties();
      KieBaseCacheEntry cacheEntry = new KieBaseCacheEntry(drlContent, kieBaseProps);
      // 将cacheEntry序列化存入Redis
      
      // 取出时重建KieBase
      KieBaseCacheEntry cachedEntry = redisTemplate.get("kiebase-key");
      KieFileSystem newKfs = kieServices.newKieFileSystem();
      newKfs.write("src/main/resources/rules/myRules.drl", cachedEntry.getDrlContent());
      KieBaseConfiguration config = kieServices.newKieBaseConfiguration(cachedEntry.getKieBaseProps());
      KieContainer kieContainer = kieServices.newKieContainer(kieServices.newKieModule(newKfs));
      KieBase kieBase = kieContainer.newKieBase(config);
      

2. 实现自定义序列化器处理KieBase

通过自定义序列化逻辑,提取KieBase的可持久化信息,绕过默认的序列化限制:

  • 针对Redis的序列化器,自定义RedisSerializer<KieBase>:
    public class KieBaseRedisSerializer implements RedisSerializer<KieBase> {
        @Override
        public byte[] serialize(KieBase kieBase) throws SerializationException {
            // 提取规则内容和配置
            Properties props = kieBase.getKieBaseConfiguration().toProperties();
            Collection<KiePackage> packages = kieBase.getKiePackages();
            // 将packages转为可序列化的格式(比如把每个package的规则转为字符串)
            List<String> ruleContents = new ArrayList<>();
            for (KiePackage pkg : packages) {
                for (Rule rule : pkg.getRules()) {
                    ruleContents.add(rule.getPackageName() + ":" + rule.getName() + ":" + rule.getLhs() + rule.getRhs());
                }
            }
            // 打包成JSON或其他序列化格式
            KieBaseSerializedDTO dto = new KieBaseSerializedDTO(props, ruleContents);
            return new ObjectMapper().writeValueAsBytes(dto);
        }
    
        @Override
        public KieBase deserialize(byte[] bytes) throws SerializationException {
            KieBaseSerializedDTO dto = new ObjectMapper().readValue(bytes, KieBaseSerializedDTO.class);
            KieServices kieServices = KieServices.Factory.get();
            KieFileSystem kfs = kieServices.newKieFileSystem();
            // 重新构建规则文件并写入kfs
            for (String ruleContent : dto.getRuleContents()) {
                // 解析规则内容,生成.drl文件并写入
                String[] parts = ruleContent.split(":");
                String pkgName = parts[0];
                String ruleName = parts[1];
                String lhs = parts[2];
                String rhs = parts[3];
                String drl = "package " + pkgName + "\nrule " + ruleName + "\nwhen " + lhs + "\nthen " + rhs + "\nend";
                kfs.write("src/main/resources/rules/" + ruleName + ".drl", drl.getBytes());
            }
            KieBaseConfiguration config = kieServices.newKieBaseConfiguration(dto.getProps());
            KieContainer kieContainer = kieServices.newKieContainer(kieServices.newKieModule(kfs));
            return kieContainer.newKieBase(config);
        }
    }
    
  • 配置RedisTemplate使用该序列化器,即可直接将KieBase存入/取出Redis。

3. 优化KieSession缓存逻辑,关联KieBase配置

如果仍需缓存KieSession,可将KieSession与对应的KieBase配置绑定缓存:

  • 缓存时,将KieSession序列化后的字节数组,与对应的KieBase配置POJO(如方案1中的KieBaseCacheEntry)存入同一个Redis键或关联键;
  • 取出时,先通过KieBase配置重建KieBase,再用该KieBase反序列化KieSession:
    // 缓存KieSession和KieBase配置
    byte[] sessionBytes = serializeKieSession(kieSession);
    redisTemplate.opsForHash().put("session-cache", "session-1", sessionBytes);
    redisTemplate.opsForHash().put("session-cache", "session-1-kb-config", cacheEntry);
    
    // 取出反序列化
    KieBaseCacheEntry cachedConfig = (KieBaseCacheEntry) redisTemplate.opsForHash().get("session-cache", "session-1-kb-config");
    KieBase kieBase = rebuildKieBase(cachedConfig);
    byte[] sessionBytes = (byte[]) redisTemplate.opsForHash().get("session-cache", "session-1");
    KieSession kieSession = kieBase.newKieSession();
    ((StatefulKnowledgeSession) kieSession).restore(sessionBytes);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:40:28