drools 6.4

一. 简介

Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。

二. 环境搭建

1. 从drools官网下载最新drools

http://www.drools.org/download/download.html

Paste_Image.png

2. eclipse的drools插件离线安装

  • 从官网下载对应版本的插件压缩包
    将下载到的压缩包解压,将features,plugins文件夹,拷贝到eclipse的dropins/drools目录(drools目录需要自己建立),然后重启eclipse
Paste_Image.png

3. 使用maven创建drools项目

  • 项目的pom中引入drools的依赖
<dependency>
    <groupId>org.jbpm</groupId>
    <artifactId>jbpm-test</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-api</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>knowledge-api</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-decisiontables</artifactId>
    <version>6.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-jsr94</artifactId>
    <version>6.4.0.Final</version>
</dependency>

三. 快速入门

  • 使用骨架库创建一个简单的java maven项目
  • 创建规则文件

Sample.drl

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
    <kbase name="dtables" packages="dtables">
        <ksession name="ksession-dtables"/>
    </kbase>
    <kbase name="process" packages="process">
        <ksession name="ksession-process"/>
    </kbase>
</kmodule>
  • 定义规则之间的关系

kmodule.xml

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
</kmodule>
  • 编写测试类
package com.sample;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class DroolsTest {

    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            KieSession kSession = kContainer.newKieSession("ksession-rules");

            // go !
            Message message = new Message();
            message.setMessage("Hello World");
            message.setStatus(Message.HELLO);
            kSession.insert(message);
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static class Message {

        public static final int HELLO = 0;
        public static final int GOODBYE = 1;

        private String message;

        private int status;

        public String getMessage() {
            return this.message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public int getStatus() {
            return this.status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

    }

}

四. 项目结构说明

Paste_Image.png

五. drools工作流程

六. 规则文件(.drl文件)

规则语法:

package /*包名,必须,且必须在第一行,不必与规则为文件的物理路径一致,若自定义函数或查询属于同一包名,不管物理位置如何,都可以调用*/

import /*需要导入的类名*/

global /*全局变量*/

function /*函数*/

query /*查询*/

rule /*规则,可以有多个*/

规则文件

package com.qc.drools;

import com.qc.model.Student;

global java.util.List.studentList;

function void sysName(){
  System.out.println("我是张三");
}

rule "规则名称"
    <属性><值>
    when
        条件 Left Hand Side
    then
        结果 Right Hand Side

package:对一个规则文件而言,package是必须定义的,必须放在规则文件第一行。特别的是,package的名字是随意的,不必必须对应物理路径,跟java的package的概念不同,这里只是逻辑上的一种区分

import:导入规则文件需要使用到的外部变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法
比如:
import com.drools.demo.point.PointDomain;
import com.drools.demo.point.PointDomain.getById;

global: 定义global全局变量,通常用于返回数据和提供服务全局变量与fact不一样,引擎不能知道全局变量的改变必须要在插入fact之前,设置global变量

function: 规则中的代码块,封装业务操作,提高代码复用函数以function开头,其它与JAVA方法类似业务代码书写采用的是标准JAVA语法

rule:定义一个规则。rule "ruleName"
一个规则可以包含三个部分

属性部分: 定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等

条件部分: 即LHS,定义当前规则的条件,如 when Message(); 判断当前workingMemory中是否存在Message对象

结果部分: 即RHS,这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用
规则事例:

rule "name"
       no-loop true
       when
               $message:Message(status == 0)
       then
               System.out.println("fit");
               $message.setStatus(1);
               update($message);
end

属性: activation-group、agenda-group、auto-focus、date-effective、date-expires、dialect、duration、duration-value、enabled、lock-on-active、no-loop、ruleflow-group、salience

salience: 它的作用是用来设置规则执行的优先级,salience 属性的值是一个数字,数字越大执行优先级越高,同时它的值可以是一个负数。默认情况下,规则的salience 默认值为0,所以如果我们不手动设置规则的salience 属性,那么它的执行顺序是随机的
int型,默认值为0

no-loop: 在DRL的then子句中,如果出现insert、update、modify、retract等方法对实例(Fact)做出修改时,当前规则执行完成后会触发该规则使其再执行一次;将no-loop设置为true则会强制规则在出现上述方法的情况下也只执行一次boolean型,默认值为false

date-effective: 该属性是用来控制规则只有在到达后才会触发,在规则运行时,引擎会自动拿当前操作系统的时候与date-effective 设置的时间值进行比对,只有当系统时间>=date-effective 设置的时间值时,规则才会触发执行,否则执行将不执行。在没有设置该属性的情况下,规则随时可以触发,没有这种限制。 date-effective 的值为一个日期型的字符串,默认情况下,date-effective 可接受的日期格式为“dd-MMM-yyyy”,例如2009 年9 月25 日在设置为date-effective 的值时,如果您的操作系统为英文的,那么应该写成“25-Sep-2009”;如果是英文操作系统“25-九月-2009”
当前规则的生效时间string型,无默认值;值中需包含日期和时间

date-expires: 该属性的作用与date-effective 属性恰恰相反, date-expires 的作用是用来设置规则的有效期,引擎在执行规则的时候,会检查规则有没有date-expires 属性,如果有的话,那么会将这个属性的值与当前系统时间进行比对,如果大于系统时间,那么规则就执行,否则就不执行。该属性的值同样也是一个日期类型,默认格式也是“dd-MMM-yyyy”,具体用法与date-effective 属性相同
当前规则的失效时间string型,无默认值;值中需包含日期和时间

enabled: 它是用来定义一个规则是否可用的。该属性的值是一个布尔值,默认该属性的值为true,表示规则是可用的,如果手工为一个规则添加一个enabled 属性,并且设置其enabled 属性值为false,那么引擎就不会执行该规则

dialect: 该属性用来定义规则当中要使用的语言类型,目前Drools5 版本当中支持两种类型的语言:mvel 和java,默认情况下,如果没有手工设置规则的dialect,那么使用的java 语言
设置规则所使用的语言
string型,默认值根据package值判断,值域为java或mvel

duration: 对于一个规则来说,如果设置了该属性,那么规则将在该属性指定的值之后在另外一个线程里触发。该属性对应的值为一个长整型,单位是毫秒,代码清单2-37 里的规则rule1 添加了duration 属性,它的值为3000,表示该规则将在3000 毫秒之后在另外一个线程里触发
设置DRL文件开始执行之后延迟多长时间开始执行这条规则
long型,无默认值

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

activation-group: 该属性的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同activation-group 属性的规则中只要有一个会被执行,其它的规则都将不再执行。也就是说,在一组具有相同activation-group 属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行。当然对于具有相同activation-group 属性的规则当中究竟哪一个会先执行,则可以用类似salience 之类属性来实现
不基于任何条件将规则分组string型,无默认值

agenda-group: 规则的调用与执行是通过StatelessSession 或StatefulSession 来实现的,一般的顺序是创建一个StatelessSession 或StatefulSession,将各种经过编译的规则的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将规则分组;只有当某个Agenda组获取到焦点(focus)时,该组的规则才会被执行string型,默认值为MAIN

auto-focus: 前面我们也提到auto-focus 属性,它的作用是用来在已设置了agenda-group 的规则上设置该规则是否可以自动独取Focus,如果该属性设置为true,那么在引擎执行时,就不需要显示的为某个Agenda Group 设置Focus,否则需要。对于规则的执行的控制,还可以使用Agenda Filter 来实现。在Drools 当中,提供了一个名为org.drools.runtime.rule.AgendaFilter 的Agenda Filter 接口,用户可以实现该接口,通过规则当中的某些属性来控制规则要不要执行。org.drools.runtime.rule.AgendaFilter 接口只有一个方法需要实现,方法体如下: public boolean accept(Activation activation); 在该方法当中提供了一个Activation 参数,通过该参数我们可以得到当前正在执行的规则对象或其它一些属性,该方法要返回一个布尔值,该布尔值就决定了要不要执行当前这个规则,返回true 就执行规则,否则就不执行
与agenda-group配合使用,设置焦点的是否可以自动获取boolean型,默认值为false

ruleflow-group: 基于ruleflow将规则分组string型,无默认值,作用是用来将规则划分为一个个的组,然后在规则流当中通过使用ruleflow-group 属性的值,从而使用对应的规则

Left Hand Side: Conditions / LHS —匹配模式(Patterns)
没有字段约束的Pattern
Person()

有文本字段约束的Pattern
Person( name == “bob” )

字段绑定的Pattern
Person( $name : name == “bob” )
变量名称可以是任何合法的java变量,$是可选的,可用于区分字段和变量

Fact绑定的Pattern
$bob : Person( name == “bob” )

字段绑定的Pattern

变量约束的Pattern
Person( name == $name )

比较操作符: > >= < <= == != contains / not contains / memberOf / not memberOf /matches/ not matches

memberOf: 判断某个Fact属性值是否在某个集合中,与contains不同的是他被比较的对象是一个集合,而contains被比较的对象是单个值或者对象

not memberOf: 与memberOf的作用相反

matches: 正则表达式匹配,与java不同的是,不用考虑'/'的转义问题

not matches: 正好相反

Right Hand Side:
insert: 往当前workingMemory中插入一个新的Fact对象,会触发规则的再次执行,除非使用no-loop限定

update: 更新workingMemory中的Fact对象

modify: 修改,与update语法不同,结果都是更新操作

retract: 删除

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 概述(Overview) 以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规...
    老羊_肖恩阅读 41,589评论 4 31
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Drools规则文件——语法属性 salience 功能:设置规制执行的优先级值:数字(数字越大执行优先级越高)...
    天堂的码头阅读 3,112评论 0 2
  • 关于亲子阅读的20句话 1.你孩子现在开始阅读并不晚。当然,多早都不会太早,胎儿也是人。 2.三岁以前最好不要指读...
    Sybil麻麻阅读 630评论 0 0
  • ■3月份的时候,一个朋友认识了一个很喜欢很向上的男孩子,她为此和男朋友分手并说明了理由,然后和喜欢的男孩子告白,虽...
    N一米八阅读 265评论 0 0