Drools规则引擎

发布时间 2023-11-27 20:51:09作者: fzy_uni

what:是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策

  基于 rete 算法的规则引擎  

  rete 算法是实现产生式系统中正向推理的高效模式匹配算法,通过形成一个 rete 网络进行模式匹配,利用基于规则的系统的时间冗余性和结构相似性特征 ,提高系统模式匹

  配效率。像 ILog、Jess、JBoss Rules 等都是基于 RETE 算法的规则引擎。其核心思想是将分离的匹配项根据内容动态构造匹配树,以达到显著降低计算量的效果。Rete 算法可以

  被分为两个部分:规则编译和规则执行 。当 Rete 算法进行事实的断言时,包含三个阶段:匹配、选择和执行,称做 match-select-act cycle

  

drools规则引擎由以下几部分构成:
  Rules(规则库)
  Facts  (工作对象)
  Production memory  (生产内存,操作rules中的规则)
  Working memory: (工作内存)
  Agenda  (议程,用于存放通过匹配器进行模式匹配后被激活的规则)

  Pattern Matcher(适配器)    将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。

 

How

  规则文件构成

    package 包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用
    import 用于导入类或者静态方法
    global 全局变量
    function 自定义函数
    query 查询
    rule end 规则体

  规则体语法结构  单行注释用"//"进行标记,多行注释以"/"开始,以" /"结束

    rule "ruleName"      ### rule:关键字,表示规则开始,参数为规则的唯一名称
      attributes    ### attributes:规则属性,是rule与when之间的参数,为可选项。
      when       ###  when:关键字,后面跟规则的条件部分。  
        LHS    ###  LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。 (左手边)

      then      ###  then:关键字,后面跟规则的结果部分

        RHS    ###  RHS(Right Hand Side):是规则的后果或行动部分的通用名称。 (右手边)
      end       ###  end:关键字,表示一个规则结束。

    ####    LHS部分还可以定义多个pattern,多个pattern之间可以使用and或者or进行连接,也可以不写,默认连接为and。

    ###  比较操作符   > >= == != < <=  contains | not contains (属性里是否包含某值)  memberOf | not memberOf(属性是否属于集合内)  matches | not matches(正则)

    例如:

    rule "add100"
      no-loop true
      lock-on-active true
      salience 1
    when
      $order : Order(price > 100 && price <= 500)    ###  $order 绑定变量名:Object(Field约束)  可以省略,通常绑定变量名的命名一般建议以$开始
    then
      $order.setScore(100);
      update($s);
    end

    //通过规则过滤器实现只执行指定规则
    kieSession.fireAllRules(new kieSession.fireAllRules(new
                        RuleNameEqualsAgendaFilter("rule_filter_1"));

    规则属性  

      salience 指定规则执行优先级   值越大越优先

      dialect 指定规则使用的语言类型,取值为java和mvel
      enabled 指定规则是否启用
      date-effective 指定规则生效时间
      date-expires 指定规则失效时间
      activation-group 激活分组,具有相同分组名称的规则只能有一个规则触发
      agenda-group 议程分组,只有获取焦点的组中的规则才有可能触发  .getAgendaGroup()
      timer 定时器,指定规则触发的时间
      auto-focus 自动获取焦点,一般结合agenda-group一起使用
      no-loop 防止死循环,防止自己更新规则再次触发
      lock-on-active no-loop增强版本。可防止别人更新规则再次出发

      global 全局变量    query查询   function函数    

      条件-LHS加强   条件元素not    条件元素exists   规则继承extend   

      结果-RHS    insert方法    update方法    modify方法    retract/delete方法

      RHS加强    halt 立即终止后面所有规则的执行    getRule  返回规则对象   

  java的springboot工程引入:jar包

  <dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>${drools.version}</version>
    <exclusions>     ##需要排除spring框架的干扰依赖
      <exclusion>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
      </exclusion>
      <exclusion>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
      </exclusion>
      <exclusion>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
      </exclusion>
      <exclusion>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
      </exclusion>
    </exclusions>
  </dependency>

 编写配置类

 @Configuratio  

 public class DroolsAutoConfiguration   

  private static final String RULES_PATH = "rules/";      ##drl规则文件 resource路径下的路径

  private KieServices getKieServices() {
    return KieServices.Factory.get();
  }
  @Bean
  @ConditionalOnMissingBean(KieFileSystem.class)
  public KieFileSystem kieFileSystem() throws IOException {
    KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
    for (Resource file : getRuleFiles()) {
      kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH +
      file.getFilename(), "UTF-8"));
    }
    return kieFileSystem;
    }
    private Resource[] getRuleFiles() throws IOException {
      ResourcePatternResolver resourcePatternResolver = new
                            PathMatchingResourcePatternResolver();
      return resourcePatternResolver.getResources("classpath*:" + RULES_PATH +
                            "**/*.*");
    }
    @Bean
    @ConditionalOnMissingBean(KieContainer.class)
    public KieContainer kieContainer() throws IOException {
      final KieRepository kieRepository = getKieServices().getRepository();
      kieRepository.addKieModule(() -> kieRepository.getDefaultReleaseId());
      KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
      kieBuilder.buildAll();
      KieContainer kieContainer =
            getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
      return kieContainer;
    }
    @Bean
    @ConditionalOnMissingBean(KieBase.class)
    public KieBase kieBase() throws IOException {
      return kieContainer().getKieBase();
    }
  }

 

 

  编写规则引擎文件.drl

    

    规则文件编码规范
    在进行drl类型的规则文件编写时尽量遵循如下规范:
    所有的规则文件(.drl)应统一放在一个规定的文件夹中,如:/rules文件夹
    书写的每个规则应尽量加上注释。注释要清晰明了,言简意赅
    同一类型的对象尽量放在一个规则文件中,如所有Student类型的对象尽量放在一个规则文件中
    规则结果部分(RHS)尽量不要有条件语句,如if(...),尽量不要有复杂的逻辑和深层次的嵌套语句
    每个规则最好都加上salience属性,明确执行顺序
    Drools默认dialect为"Java",尽量避免使用dialect "mvel"

  

  WorkBench

    WorkBench是KIE组件中的元素,也称为KIE-WB,是Drools-WB与JBPM-WB的结合体。它是一个可视化的规则编辑器。WorkBench其实就是一个war包。