Drools只执行一个规则或者执行完当前规则之后不再执行其他规则(转)

转自https://www.cnblogs.com/atomicbomb/p/7251814.html

 kieSession.fireAllRules(1); :只执行其中一条可执行规则

Drools是一款基于Java的开源规则引擎
  实现了将业务决策从应用程序中分离出来。

  优点:
    1、简化系统架构,优化应用
    2、提高系统的可维护性和维护成本
    3、方便系统的整合
    4、减少编写“硬代码”业务规则的成本和风险

Drools的基本工作工程
  我们需要传递进去数据,用于规则的检查,调用外部接口,同时还可能获取规则执行完毕之后得到的结果

Fact对象:
  指传递给drools脚本的对象,是一个普通的javabean,原来javaBean对象的引用,可以对该对象进行读写操作,并调用该对象的方法
  当一个java bean插入到working Memory(内存存储)中,规则使用的是原有对象的引用,规则通过对fact对象的读写,
  实现对应用数据的读写,对其中的属性,需要提供get和set方法,规则中可以动态的前往working memory中插入删除新的fact对象

Drools的基础语法:
  包路径,引用,规则体 (其中包路径和规则体是必须的)

Drl文件内容:
  例子:
    hello.drl文件如下:

package rules.testword
rule "test001"
  when
    //这里如果为空,则表示eval(true)
  then
    System.out.println("hello word");
end

  package:包路径,该路径是逻辑路径(可以随便写,但是不能不写,最好和文件目录同名,以(.)的方式隔开),规则文件中永远是第一行
  rule:规则体,以rule开头,以end结尾,每个文件可以包含多个rule ,规则体分为3个部分:LHS,RHS,属性 三大部分
  LHS:(Left Hand Side),条件部分,在一个规则当中“when”和“then”中间的部分就是LHS部分,在LHS当中,可以包含0~N个条件,如果
    LHS为空的话,那么引擎会自动添加一个eval(true)的条件,由于该条件总是返回true,所以LHS为空的规则总是返回true。
  RHS:(Right Hand Side),在一个规则中“then”后面的部分就是RHS,只有在LHS的所有条件都满足的情况下,RHS部分才会执行。
    RHS部分是规则真正做事情的部分,满足条件触发动作的操作部分,在RHS可以使用LHS部分当中的定义的绑定变量名,设置的全局变量、
    或者是直接编写的java代码,可以使用import的类。
    不建议有条件判断。
    可以使用快速操作working Memory的宏函数和对象,比如insert/insertLogical,update/modify和retract就可以实现对当前Working Memory中的Fact对象
    进行新增,修改,或者删除,可以使用drool宏对象,Drools还提供了kcontext的宏对象,该对象可以直接访问当前Working Memory的KnowledgeRuntime。

  import:导入规则文件需要使用到的外部变量,可以导入类,也可以是这个类中的静态方法
    例如:
      import com.dinpay.dpp.rcp.service.util.RuleLogUtil; 导入类
      import com.dinpay.dpp.rcp.service.util.RuleLogUtil.getLog;//导入静态方法

Drools的API调用
  API可以分为三类:规则编译,规则收集,规则执行

  1、Kmodule.xml的编译
    存放在src/main/resources/META-INF/文件夹下

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules.testword">
        <ksession name="session"/>
    </kbase>
</kmodule>        

    1)、可包含多个kbase,任意但不能重名
    2)、有个packages,就是src/main/resources下面的文件夹名称,可定义多个包,用逗号隔开
    3)、ksession都一个name,任意字符串但不能重名,可以有多个
    4)、在运行时、KieContainer会根据*Model对象来创建KieModule,KieBase,KieSession对象,其中KieModule和KieBase只会创建一次,而KieSession则可能创建多次

  2、API说明,引入drools依赖jar包,drools-core,kie-api,drools-compiler

KieSession;
  用于与规则引擎进行交互的会话
  分为两类:
    有状态KieSession:KieSession会在多次与规则引擎进行交互中,维护会话状态,type属性值是stateful,
             最后需要清理KieSession维护的状态,调用dispose()方法

    无状态StatelessKieSession:StatelessKieSession隔离了每次与规则引擎的交互,不会维护会话状态,无副作用,type属性值是stateless
       应用场景:数据校验,运算,数据过滤,消息路由,任何能被描述成函数或公式的规则

Drools内部功能详细介绍
规则文件
  一个标准的规则文件的结构代码:
    package package-name(包名,必须的,只限制于逻辑上的管理,若自定义查询或者函数属于同一个包名,不管物理位置如何,都可以调用)
    imports (需要导入的类名)
    globals (全局变量)
    functions (函数)
    queries (查询)
    rules (规则,可以多个)

package在规则文件中是第一行,其他的顺序可以是无序的,package对于规则文件中规则的管理只限于逻辑上的管理

规则语言
  rule “name”
    attributes ---->属性
    when
      LHS ---->条件
    then
      RHS ---->结果
  end
  一个规则包含三部分:唯有attributes部分可选,其他都是必填信息
    定义当前规则执行的一些属性等,比如是否可被重复执行,过期时间,生效时间等
    LHS:定义当前规则的条件,如 when Message();判断当前workingMemory中是否存在Message对象
    RHS:可以写java代码,即当前规则条件满足执行的操作,可以直接调用Fact对象的方法来操作应用

      LHS:如果LHS部分为空,自动添加一个eval(true)操作
           LHS部分是由一个或多个条件组成,条件又称为pattern(匹配模式),多个pattern之间可以使用 and 或 or来进行连接,同时还可以使用小括号来确定pattern的优先级
         【绑定变量名:】Object(【filed 约束】)
         对于一个pattern来说"绑定变量名"是可选的,如果在当前规则的LHS部分的其他pattern要使用这个对象,那么可以通过为该对象绑定设定一个
        绑定变量名来实现对其的引用,对于绑定变量的命名,通常的做法是为其添加一个 "$"符号作为前缀,可以和Fact对象区分开来
        绑定变量可以用于对象上,可以用于对象属性上,"field约束"是指当前对象里相关字段的条件限制

rule "rule1"
    when
        $customer:Customer()
    then
        <action>...
end            

  规则中LHS部分单个pattern(模式)的情形。
  规则中"$customer"就是绑定到Customer对象的"绑定变量名",该规则的LHS部分表示,要求Fact对象必须是Customer类型,该条件满足,那么它的LHS会返回true

rule "rule1"
     when
           $customer:Customer(age>20,gender=="male")
           Order(customer==$customer,price>1000)
     then
           <action>...end

  第一个pattern有三个约束

    1、对象类型必须是Customer;
    2、Customer的age要大于20
    3、Customer的gender要是male
  第二个pattern有三个约束
    1、对象类型必须是Order
    2、Order对应的Customer必须是前面那个Customer
    3、当前这个Order的price要大于1000
    这两个pattern没有符号连接,在Drools当中没有连接符号,默认是and,只有两个pattern(模式)都满足才会返回true,每行可以用";"结束

  约束连接
    对象内部的多个约束连接 "&&"(and),"||"(or)和","(and)来实现
    如果记性常量的比较,必须通过eval(条件)或者对象引用比较对象属性,不能单独引用
    12个类型比较操作符 >|<,>=|<=,==|!=,contains|not contains,memberOf|not memberOf,matches|not matches

Drools属性说明
  salience优先级
    作用:设置规则执行的优先级,值是一个数字,数字越大执行的优先级越高,它的值可以是一个负数,默认值是0
         如果我们不手动设置salience属性值,则执行顺序是随机的

  no-loop防止死循环
    在一个规则中如果条件满足就对Working Memory当中的某个Fact对象进行修改,比如使用update将其更新到当前的Working Memory当中,这时候引擎会再次检查所有的规则是否满足条件,如果满足会再执行,可能会出现死循环
    作用:用来控制已经执行过的规则条件再次满足时是否再次执行,默认是false,如果属性值是true,表示该规则只会被规则引擎检查一次,如果满足条件就执行规则的RHS部分
    注意:如果引擎内部因为对Fact更新引起引擎再次启动检查规则,那么它会忽略掉所有的no-loop属性设置为true的规则

    例如以下情况:计算设置了no-loop为true也会出现死循环
    

package rules.testword
import com.drools.test.Person
    rule test001
        no-loop true
        when
      $p:Person(name=="张三");
     then
      $p.setAge(50);
      update($p);
      System.out.println("设置no-loop时的效果");
  end

rule test002
  no-loop true
  when
    $p:Person(age==50);
  then
    $p.setName("张三");
    update($p);
    System.out.println("设置no-loop时的效果");
end  

  date-effective日期比较小于等于

  date-expires日期比较大于

  Dialect方言

  Enabled是否可用

  lock-on-active规则执行一次
    当在规则上使用ruleflow-group属性或agenda-group属性的时候,将lock-on-active属性的值设置为true,可以避免因某些Fact对象被修改而使已经执行过
    的规则再次被激活执行。可以看出该属性与no-loop属性有相似之处,no-loop属性是为了避免Fact修改或调用了insert,retract,update之类导致
    规则再次激活执行,这里lock-on-active属性也是这个作用,lock-on-active是no-loop的增强版。
    作用:在使用ruleflow-group属性或agenda-group属性的时候,默认是false,设置为true,该规则只会执行一次

  activation-group分组

  agenda-greoup议程分组
    规则的调用与执行是通过StatelessSession和ksession来实现的,一般的顺序是创建一个StatelessSession或ksession,
    将各种经过编译的规则的package添加到session当中,接下来将规则当中可能用到的Global对象和Fact对象插入到Session当中,
    最后调用fireAllRules方法来触发,执行规则,在没有调用最后一步分fireAllRules方法之前,
    所有的规则及插入的Fact对象都存放在Agenda表的对象当中,这个Agenda表中的每个规则及其匹配相关的业务数据叫做Activation,
    在调用fireAllRules方法后,这些Activation会依次执行,这些位于Agenda表中的Activation的执行顺序在没有设置相关用来
    控制顺序的时(比如:salience属性),它的执行顺序是随机不确定的。

    agenda-group是用来在Agenda基础上,对现有的规则进行再次分组,具体的分组方法可以采用为规则添加agenda-group属性来实现,
    agenda-group属性的值也是一个字符串,通过这个字符串,可以将规则分为若干个agenda group,默认情况下,引擎在调用这些
    设置了agenda-group属性的规则的时候需要指定某个agenda group得到Focus(焦点),这样位于该agenda group当中的规则才会触发执行,否则将不执行

    实际应用中agenda-group可以和auto-focus属性一起使用

  auto-focus焦点分组

  ruleflow-group规则流

Drools drl注释的使用
  单行// 多行/**/

Drools函数的使用
  insert插入
  语法格式:insert(new Object());

  insertLogical插入

  update修改
  语法格式:update(Object());

  retract删除功能

drools常用方法
  方法名称              用法格式           含义
  getWorkingMemory()   drools.getWorkingMemory()    获取当前WorkingMemory对象
  halt()              drools.halt()            在当前规则执行完成之后,不再执行其他未执行的规则
  getRule()            ——               获取当前规则对象
  insert(new Object)     ——                       插入指定对象
  update(new Object)    ——                                                 更新指定对象
  update(FactHandleObject) ——                     更新指定对象
  retract(new Object)   ——                  删除指定对象

Drools语法篇之Global全局变量
  global不是用来做数据共享的,session会影响到global的用法
  注意:
    1、常量值是不能改变的
    2、包装类是不能改变的
    3、类似javaBean,List这类的操作,是可以改变内容的,但内存地址是不会变的

Drools语法篇之查询Query

Drools语法篇之类的声明及元数据的用法
    声明新类型:使用关键字declare,紧接着字段列表,和关键字end。
    例如:

declare Address
    number:int
    streetName:String
    city:String
end

原文地址:https://www.cnblogs.com/ffaiss/p/10995891.html

时间: 2024-08-03 11:14:02

Drools只执行一个规则或者执行完当前规则之后不再执行其他规则(转)的相关文章

如何让程序只在内存中执行一个

在WinForm或者Console程序中,可以通过可以遍历所有现在正在执行的进程,如果有同名的进程存在,那么说明这个程序已经启动了一个了,此处就不再启动了.如果没有同名进程的存在,说明这个程序还没有启动过,此时我们可以启动一个. public static void Main() { string strModuleName = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; string strProc

带您理解SQLSERVER是如何执行一个查询的

原文地址:http://www.cnblogs.com/lyhabc/p/3367274.html 看这篇文章之前,阁下可以先看一下下面的文章 SQLSERVER独特的任务调度算法"SQLOS" SQL Server SQLOS 的任务调度[转] 翻译自: http://rusanu.com/2013/08/01/understanding-how-sql-server-executes-a-query/ http://www.codeproject.com/Articles/6303

Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架

转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架.Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器. Leaf 的关注点: 良好的使用体验.Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率 稳定性.Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃 多核支持.Leaf 通过模块机制和 leaf

如何在linux中执行一个脚本

---恢复内容开始--- 如何在LINUX中在系统启动时自动执行一个执行脚本 如果是开机马上执行的脚本,可以将脚本写到rc.local中: 如果是用户登录后自动执行脚本,可以将脚本写到相应的用户目录下"-/.bash_profile",若脚本"-/.bash_profile"不存在,可以直接拷贝"/etc/profile"命名为"-/.bash_profile": 如果是要任一用户登录后自动执行脚本,可以将脚本写到"

一定间隔时间下重复执行一个函数的几个方法

如果有个操作,我们需要过一会儿再做,或者每隔一段时间就要做一次.可以有很多种做法. 独立线程 是的,对.NET Framework本身一知半解的程序员才会使用这种方案.不过,现实中这个方案其实并不少见. public static void Repeat(this Action action, TimeSpan interval) { new Thread(new ThreadStart(() => { while(true) { Thread.Sleep(interval); action()

【转载】W3C下的冒泡和捕获机制。到底是冒泡呢。还是捕获呢。一个DOM元素绑定多个事件时如何执行。

原文  http://blog.csdn.net/u011719449/article/details/23787627 在准备阿里前端面试的时候看到这么一道题. 一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何. 这导致了我对冒泡和捕获又进一步深入的了解.(永远都在发现自己知识匮乏的日子中度过人生真是好抓急啊.) 首先冒泡和捕获是怎么一回事. 简单点说.冒泡就是从下往上,像鱼吐泡,泡泡是从下往上升的,也就是DOM元素被触法事件时(此时的dom元素为目标元素),目

[译]SQL Passion Week 1: SQL Server如何执行一个查询

SQLpassion Performance Tuning Training Plan 个人学习翻译,如有谬误,请不吝指出,感谢.  Week 1: SQL Server如何执行一个查询   在我们进入SQL Server性能调优的繁杂细节之前, 我想先列举一下SQL Server如何执行一个查询(query)的结构, 这部分内容非常重要, 因为了解这些概念, 对我们以后的性能调优课程会理解的更加深刻. 下面的图为我们展示了SQL Server执行查询过程中所包含的几个主要组成部分: SQL S

[Win32]一个调试器的实现(八)单步执行

[Win32]一个调试器的实现(八)单步执行 作者:Zplutor 出处:http://www.cnblogs.com/zplutor/ 本文版权归作者和博客园共有,欢迎转载.但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 上回讲解了如何实现断点功能,这回讲解如何实现与断点紧密相关的单步执行功能.单步执行有三种类型:StepIn,StepOver和StepOut,它们的实现方式比较多样化,单独实现它们的话并不困难,但是将它们整合到一起就比较困难了,

在bat脚本中执行另一个bat脚本,下面的命令不再执行

在bat脚本中执行另一个bat脚本,下面的命令不再执行,如下bat.bat: bat1.bat bat2.bat 在执行完bat1.bat 之后直接返回,bat2.bat没有被执行,这种情况下,用call bat1.bat即可解决,如下: call bat1.bat call bat2.bat 至于是什么原因也没有去分析,毕竟bat脚本很少写,能用就好.