drools 如何动态加载规则

drools版本:7.0
语言:java8
描述:动态从数据库中加载规则,并且加载到工作内存中

 

最终实现效果:从数据库中读取数据生成drl格式的字符串以后,可以一次性加载到工作内存中,也可以逐次加载到内存中进行build,而之前已经build好的规则不会消失。

下面是具体实现过程:

首先drools提供了常见的两种加载规则的方式,一种是通过定义kmodule.xml的方式进行加载,并且在对应的package下写好drl规则文件即可,xml文件如下,规则文件略。

 <?xml version="1.0" encoding="UTF-8"?>
    <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="rule1KB" packages="rules">
        <ksession name="rule1KS"/>
    </kbase>
    </kmodule>

 

通过这种xml加载的方式在具体java代码中获取session会话的方式是这样的:

KieContainer kc =KieServices.Factory.get().getKieClasspathContainer("rule1KB");
KieSession kieSession = kc.newKieSession("rule1KS");

 

注意获取KieContainerKieSession 的名称和xml中的对应。

但是在实际的动态加载中,drl格式的文件极有可能不是写好了的,而是从数据库中取出来数据,然后通过拼接字符串的方式动态生成的(至少我们现在这个项目就要这样做(_))。
所以采用这种方式就有问题了,好在drools官方提供了另一种加载规则文件的方式,具体代码如下:

 public KieContainer loadForRule(String drlStr) {
        KieServices ks = KieServices.Factory.get();
        KieRepository kr = ks.getRepository();
        KieFileSystem kfs = ks.newKieFileSystem();

        kfs.write("src/main/resources/rules/" + drlStr.hashCode() + ".drl", drlStr);
        
        // 将KieFileSystem加入到KieBuilder
        KieBuilder kb = ks.newKieBuilder(kfs);

        // 编译此时的builder中所有的规则
        kb.buildAll();
        if (kb.getResults().hasMessages(Message.Level.ERROR)) {
            throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
        }

        return ks.newKieContainer(kr.getDefaultReleaseId());
    }

 

通过上面这段代码实际上已经可以通过动态加载的方式拿到了一个KieContainer 类,继续通过KieContainer 获取到KieSession会话即可(实际上创建一次会话代价极低),具体一行代码如下:

KieSession kieSession = kContainer.newKieSession();

但是通过上面这段代码,每次都是重新加载,会出现这样的问题:现在加载了A规则,再去加载B规则,A规则已经不存在与工作内存中了,这个问题简单思考一下应该就是每次的Kie里面的对象都是重新new的,所以每次都是重新保存,这明显和实际要求不合,最直接想到的应该就是缓存一个KieContainer 方法,但是这种方式没有成功,最后采用全局缓存了kieFileSystemkieRepository进行处理。具体代码如下(省略了get/set方法):

public class KieUtils {
    private static KieContainer kieContainer;

    private static KieSession kieSession;

    private static KieServices kieServices;

    private static KieRepository kieRepository;

    private static KieFileSystem kieFileSystem;

    public static void initAndNotClear(){
        if (Objects.isNull(kieServices)) 
            kieServices = KieServices.Factory.get();

        if (Objects.isNull(kieRepository)) 
            kieRepository = kieServices.getRepository();

        if (Objects.isNull(kieFileSystem)) 
            kieFileSystem = kieServices.newKieFileSystem();
    }
}

 

使用上面这个类进行缓存,将上面的代码获取对应类的地方替换回去,比如:

KieUtils.initAndNotClear();
KieFileSystem kfs = KieUtils.getKieFileSystem();

对于这种方式的思考:
这种方式实际上还是buildKieFileSystem 中的所有的规则,实际上是一种假的添加新的规则进原规则体系中编译的方式,但实际解决了问题,并且因为动态生成最耗时间的地方在生成字符串,这种方式字符串是不用重新生成了,一般测试编译所有规则的时间是以秒级单位的,并且RETE算法本身就是一种以空间换取时间的算法,只要在规则触发时速度够快,编译时间稍微多耗一点,还是可以接受的。

以上为转载:https://www.jianshu.com/p/371d4a2a5866

 

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Drools是一个基于规则引擎的开源项目,允许用户定义和管理业务规则,并将其与应用程序集成。Drools的一个重要特性是能够动态更新规则,以便在运行时更改应用程序的行为。 使用Drools动态更新规则的过程如下: 1. 配置规则引擎:在应用程序中集成Drools,并配置规则引擎的相关参数,如规则库的位置、编译方式等。 2. 定义规则:使用Drools提供的语法,定义需要的规则规则由条件和动作组成,条件用于匹配输入数据,而动作则定义了规则执行时应该执行的操作。 3. 加载规则:将规则加载Drools规则引擎中。可以选择在应用程序初始化时加载规则,或者在运行时动态加载规则。 4. 动态更新规则:在运行时,通过修改规则库中的规则文件或从数据库、文件等外部来源加载新的规则,实现动态更新规则Drools提供了API接口,可以通过调用相关方法动态添加、修改或删除规则。 5. 触发规则引擎执行:一旦规则库发生变化,需要手动或自动触发规则引擎执行规则Drools提供了执行规则的方法,可以在应用程序中调用以触发规则的执行。 动态更新规则可以带来很多好处。首先,它允许业务人员在不修改应用程序代码的情况下改变业务逻辑,提高了灵活性和可维护性。其次,动态更新规则可以在不停机的情况下进行,不会影响应用程序的正常运行。最后,它还可以减少应用程序的维护成本,因为业务规则不再需要硬编码在代码中,而是可以通过规则引擎进行管理和维护。 综上所述,Drools动态更新规则功能可以帮助应用程序实现灵活的业务逻辑,并提供可维护和可扩展的规则管理机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值