Drools详解

2021-11-10  本文已影响0人  Tiger_Lam

Drools规则引擎的结构示意图

企业微信截图_16365257039225.png image.png

Drools相关概念

Drools原理

DRL解释执行流程

Drools规则是在Java应用程序上运行的,其要执行的步骤顺序由代码确定。为了实现这一点,Drools规则引擎将业务规则转换成执行树,如下图所示:
image.png
image.png
当到达一个Fact与规则相匹配的节点时,规则评估会将规则操作与触发数据添加到一个叫作议程(Agenda)的组件中,如果同一个Fact与多个规则相匹配,就认为这些规则是冲突的,议程(Agenda)使用冲突解决策略(Conflict Resolution strategy)管理这些冲突规则的执行顺序。整个生命周期中,规则评估与规则执行之间有着明确的分割。规则操作的执行可能会导致Fact的更新,从而与其他规则相匹配,导致它们的触发,称之为前向链接。

规则引擎工作方式

image.png

1.Pattern Matching:对新的数据和被修改的数据进行规则的匹配称为模式匹配.
2.Production Memory:被访问的规则.
3.Agenda:负责具体执行推理算法中被激发规则的结论部分,同时 Agenda 通过冲突决策策略管理这些冲突规则的执行顺序.

Drools 中规则冲突决策策略有:
Drools有专门的规则语法drl,就是专门描述活动的规则是如何执行的
## rule.drl文件内容如下
package com.alibaba.rules

import com.alibaba.Order

rule "zero"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(point <= 300)
    then
        System.out.println("无赠品");
        doSth($s);
end

rule "giftOne"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 300 && amout <= 500)
    then
        System.out.println("Dior限量口红");
        doSth($s);
end

rule "giftTwo"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 500 && amout <= 700)
    then
        System.out.println("TF限量口红");
        doSth($s);
end

rule "giftThree"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 700 && amout <= 900)
    then
        System.out.println("SK-II套装");
        doSth($s);
end

rule "giftFour"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 900 && amout <= 1100)
    then
        System.out.println("MCM双肩包");
        doSth($s);
end

rule "giftFive"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 1100)
    then
        System.out.println("RADO雷达限量表");
        doSth($s);
end 

说明:

这里需要有一个配置文件告诉代码规则文件drl在哪里,在drools中这个文件就是kmodule.xml,放置到resources/META-INF目录下。
kmodule.xml内容如下:

<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.drools.org/xsd/kmodule">
  <configuration>
    <property key="drools.evaluator.supersetOf" value="org.mycompany.SupersetOfEvaluatorDefinition"/>
  </configuration>
  <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1">
    <ksession name="KSession2_1" type="stateful" default="true"/>
    <ksession name="KSession2_2" type="stateless" default="false" beliefSystem="jtms"/>
  </kbase>
  <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">
    <ksession name="KSession3_1" type="stateful" default="false" clockType="realtime">
      <fileLogger file="drools.log" threaded="true" interval="10"/>
      <workItemHandlers>
        <workItemHandler name="name" type="org.domain.WorkItemHandler"/>
      </workItemHandlers>
      <calendars>
        <calendar name="monday" type="org.domain.Monday"/>
      </calendars>
      <listeners>
        <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener"/>
        <agendaEventListener type="org.domain.FirstAgendaListener"/>
        <agendaEventListener type="org.domain.SecondAgendaListener"/>
        <processEventListener type="org.domain.ProcessListener"/>
      </listeners>
    </ksession>
  </kbase>
</kmodule>

说明:

规则中的条件操作符

Drools提供了十二中类型比较操作符:< 、<=、>、>=、==、!=、contains、not contains、memberOf、not memberOf、matches、not matches,并且这些条件都可以组合使用。

规则中的结果部分

Demo
工程结构
image.png
依赖文件pom.xml

<!--规则引擎drools-->
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.0.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.0.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-decisiontables</artifactId>
    <version>7.0.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-templates</artifactId>
    <version>7.0.0.Final</version>
</dependency>

<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-api</artifactId>
    <version>7.0.0.Final</version>
</dependency>
配置文件kmodule.drl

package com.rules
import model.ProtocolType
dialect "java"

rule "jk16"
    when
        $protocol : ProtocolType(data matches "^1A12.*16$" )
    then
        $protocol.setType("xx燃气表协议");
        System.out.println("触发规则1:"+$protocol.getData());
     end

rule "jkstd"
    when
        $protocol : ProtocolType(data matches "18.*26",length == 10)
    then
        $protocol.setType("xx水表标准协议");
        System.out.println("触发规则2:"+$protocol.getData());
     end
测试程序Main.java

@Slf4j
public class Main {

    @Test
    public void test() {

        KieServices ks = KieServices.Factory.get();
        KieContainer kContainer = ks.getKieClasspathContainer();
        KieSession kSession = kContainer.newKieSession("ksession-rules");

        ProtocolType protocolType = new ProtocolType();
        protocolType.setData("1A1212345616");
        protocolType.setLength(12);
        kSession.insert(protocolType);
        kSession.fireAllRules();
        kSession.dispose();
        System.out.println(protocolType);

        log.info(protocolType.getType());
    }

}

触发规则1:1A1212345616
ProtocolType(data=1A1212345616,length=12,type=xx燃气表协议)
2020-08-19 18:21:35 [main] [io.example.demo.Main.test(Main.java:35)] - [INFO] xx燃气表协议

Process finished with exit code 0

Drools中的坑

Drools与SpringBoot集成时,与热部署工具spring-boot-devtools存在类加载器冲突的问题,会导致所有的规则失效。在drools的官方网站中有人提出了这个问题,并认为是个bug,但是drools的开发者认为这不是一个bug。

drools用的是lancher classloader,而devtools会把我们自己编写的model认为是会随时更改的类,所以采用的是Restart ClassLoader类加载器进行加载(为了快速进行热部署),devtools会有两个类加载器,一个Classloader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为 Restart ClassLoader。当采用Launcher ClassLoader加载的A 类与Restart Class Loader的A类进行对比时,发现不一致,所以drools引擎自然无法进行识别。

所以解决办法就是将devtools的maven依赖去掉即可,或者采用drools官网中说明的其它方法。

上一篇下一篇

猜你喜欢

热点阅读