Drools规则引擎介绍

目录

1. 排班中遇到的烦恼

2. 规则引擎介绍

3. 解决排班中的烦恼

4. drools应用扩展

排班中遇到的烦恼

排班最原始的需求是,A一种规则,B三种规则,C一种规则。实现的方式是,先拿excel将排班的各种需求画出来。然后使用java代码实现。代码如下:

if(type.equals("A")){
    复杂的代码逻辑
    此处省略一百行
}else if(type.equals("B1")){
    复杂的代码逻辑
    此处省略一百行
}else if(type.equals("B2")){
    复杂的代码逻辑
    此处省略一百行
}else if(type.equals("B3")){
    复杂的代码逻辑
    此处省略一百行
}else if(type.equals("C")){
    复杂的代码逻辑
    此处省略一百行
}

过了一段时间,需求变了,要求每周休息的日期不一样。绞尽脑汁,实现了我们每周休息日期不一样的需求。

又过了一段时间,需求又变了,要求A又多了一种排班,以前是早中晚三班倒,现在是早晚两班倒。好吧,继续按照需求修改。

又过了一段时间,需求继续改动。。。

造成的结果是,代码越来愈复杂,修改以及维护起来越来越麻烦。因此,有必要找到一种技术可以将排班规则和代码解耦,不管规则如何变化,执行端不用动。

规则引擎

相关介绍

规则引擎是一种嵌套在应用程序种的组件,它实现了将业务规则从应用程序代码中分离出来,
使复杂的业务规则实现变得简单,也可以动态修改业务规则,从而快速的响应需求变更。


image.png

java开源的规则引擎有:Drools、Easy Rules、Mandarax、IBM ILOG。使用最为广泛并且开源的是Drools。

Drools 介绍

Drools 是一个基于Charles Forgy's的RETE算法的,易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。
业务分析师人员或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业务规则。

Drools 是用Java语言编写的开放源码规则引擎,使用Rete算法对所编写的规则求值。Drools允许使用声明方式表达业务逻辑。可以使用非XML的本地语言编写规则,从而便于学习和理解。并且,还可以将Java代码直接嵌入到规则文件中,这令Drools的学习更加吸引人。

Drools 优点

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

解决排班中的问题

drools有专门的规则语法drl,就是专门描述排班规则是如何执行的,按照A排班规则需求规则如下:

arrangeA.drl 文件内容


import com.hit.eryi.brms.EmployeeDto;



function String pattern1(){
   String str = "{\"w1\":0,\"w2\":4 ,\"w3\":0 ,\"w4\":2 ,\"w5\":2 ,\"w6\":2,\"w7\":4 }";
   return str;
}

function String pattern2(){
   String str = "{\"w1\":4,\"w2\":0 ,\"w3\":4 ,\"w4\":0 ,\"w5\":2 ,\"w6\":2,\"w7\":2 }";
   return str;
}

function String pattern3(){
   String str = "{\"w1\":0,\"w2\":2 ,\"w3\":2 ,\"w4\":4 ,\"w5\":0 ,\"w6\":4,\"w7\":4 }";
   return str;
}

function String pattern4(){
   String str = "{\"w1\":2,\"w2\":0 ,\"w3\":2 ,\"w4\":0 ,\"w5\":4 ,\"w6\":4,\"w7\":4 }";
   return str;
}

function String pattern5(){
   String str = "{\"w1\":2,\"w2\":4 ,\"w3\":0 ,\"w4\":4 ,\"w5\":0 ,\"w6\":2,\"w7\":2 }";
   return str;
}

rule "g1-01"
    when
        $p : EmployeeDto((order%5) == 1);
    then
         StringBuffer stringBuffer = new StringBuffer();
         stringBuffer.append("[");
         stringBuffer.append(pattern1()).append(",");
         stringBuffer.append(pattern2()).append(",");
         stringBuffer.append(pattern3()).append(",");
         stringBuffer.append(pattern4()).append(",");
         stringBuffer.append(pattern1()).append(",");
         stringBuffer.append(pattern1());
         stringBuffer.append("]");
         $p.setArrangeJson(stringBuffer.toString());
end
rule "g1-02"
    when
        $p : EmployeeDto((order%5) == 2);
    then
        //$p.setArrangeJson("["+ pattern2() +","+ pattern3()+"," +pattern4()+","+ pattern5()+","+ pattern1() +","+ pattern2()+"]"  );
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("[");
        stringBuffer.append(pattern2()).append(",");
        stringBuffer.append(pattern3()).append(",");
        stringBuffer.append(pattern4()).append(",");
        stringBuffer.append(pattern5()).append(",");
        stringBuffer.append(pattern2()).append(",");
        stringBuffer.append(pattern2());
        stringBuffer.append("]");
        $p.setArrangeJson(stringBuffer.toString());

end

rule "g1-03"
    when
        $p : EmployeeDto( (order%5) == 3);
    then
       //$p.setArrangeJson("["+ pattern3() +","+ pattern4()+"," +pattern5()+","+ pattern1()+","+ pattern2() +","+ pattern3()+"]"  );
       StringBuffer stringBuffer = new StringBuffer();
       stringBuffer.append("[");
       stringBuffer.append(pattern3()).append(",");
       stringBuffer.append(pattern4()).append(",");
       stringBuffer.append(pattern5()).append(",");
       stringBuffer.append(pattern1()).append(",");
       stringBuffer.append(pattern3()).append(",");
       stringBuffer.append(pattern3());
       stringBuffer.append("]");
       $p.setArrangeJson(stringBuffer.toString());

end
rule "g1-04"
    when
        $p : EmployeeDto( (order%5) == 4);
    then
        //$p.setArrangeJson("["+ pattern4() +","+ pattern5()+"," +pattern1()+","+ pattern2()+","+ pattern3() +","+ pattern4()+"]"  );
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("[");
        stringBuffer.append(pattern4()).append(",");
        stringBuffer.append(pattern5()).append(",");
        stringBuffer.append(pattern1()).append(",");
        stringBuffer.append(pattern2()).append(",");
        stringBuffer.append(pattern4()).append(",");
        stringBuffer.append(pattern4());
        stringBuffer.append("]");
        $p.setArrangeJson(stringBuffer.toString());

end

rule "g1-05"
    when
        $p : EmployeeDto( (order%5) == 0);
    then
        //$p.setArrangeJson("["+ pattern5() +","+ pattern1()+"," +pattern2()+","+ pattern3()+","+ pattern4() +","+ pattern5()+"]"  );
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("[");
        stringBuffer.append(pattern5()).append(",");
        stringBuffer.append(pattern1()).append(",");
        stringBuffer.append(pattern2()).append(",");
        stringBuffer.append(pattern3()).append(",");
        stringBuffer.append(pattern5()).append(",");
        stringBuffer.append(pattern5());
        stringBuffer.append("]");
        $p.setArrangeJson(stringBuffer.toString());

end

  • package 与Java语言类似,drl的头部需要有package和import的声明,package不必和物理路径一致。
  • import 导出java Bean的完整路径,也可以将Java静态方法导入调用。
  • rule 规则名称,需要保持唯一 件,可以无限次执行。
  • no-loop 定义当前的规则是否不允许多次循环执行,默认是 false,也就是当前的规则只要满足条件,可以无限次执行。
  • lock-on-active 将lock-on-active属性的值设置为true,可避免因某些Fact对象被修改而使已经执行过的规则再次被激活执行。
  • salience 用来设置规则执行的优先级,salience 属性的值是一个数字,数字越大执行优先级越高, 同时它的值可以是一个负数。默认情况下,规则的 salience 默认值为 0。如果不设置规则的 salience 属性,那么执行顺序是随机的。
  • when 条件语句,就是当到达什么条件的时候
  • then 根据条件的结果,来执行什么动作
  • end 规则结束

drools语法

Drools 其他用法

  1. 定时器

package com.sample;
 
 
import java.text.SimpleDateFormat;
import java.util.Date;
 
global java.text.SimpleDateFormat fmt;
 
rule "timer"
    // 定时器的两种类别
    //  1. java.util.Timer
    //      1. 定时执行
    //      2. 重复执行
    //  2. crontab
    //      linux上crontab形式的定时
    //      也同时支持定时和重复两种
    
 
    // Timer
    // 1. 定时执行
    //      timer(int: delay)
    //      关键字就是timer,但是不会有粗体提示
    //      同java.util.Timer,单个参数表示的是延时时间,延时指定时间之后再执行程序,从而达到延时的目的
    //      注意关键字 int,还有冒号
    //  2. 重复执行
    //      timer(int: delay interval)
    //      还是java.util.Timer的用法
    //      框架还是不变,第一个参数表示延时时间, 第二个表示重复执行间隔
    
    
    
    // crontab
    // 1. 基本结构
    //      timer(cron: * * * * * ?)
    //      1. 主关键字一致,类型通过关键字区别  cron/int
    //      2. 参数类型和linux的crontab任务写法一致,末尾多了个问号
    //  2. 参数解释
    //      0. 对应
    //          秒 分 时 天 月
    //      1. 定时执行
    //          比如:三月二十八日二十三点四十五分五十八秒  ==>  58 45 23 28 3
    //          到了指定时间,就会自动执行任务
    //          ps: 多点定时   三点和五点和八点整  ==>  0 0 3,5,8 * *
    //      2. 周期执行
    //          一个除就能够表示"每",单位当然就是看所占的位置了
    //          每二十秒: */20 * * * *
    //  3. 对比
    //      1. 缺点
    //          和上面的定时器相比,缺点在于没有"缓冲",到了时间必定执行
    //      2. 有点
    //          1. 准时,直接定时,而不是靠延时定时
    //          2. 用法多样,功能强大
    //  4. 扩展
    //      1. 开关和周期
    //          定时器的所谓延时和周期重复是完全独立的,但是crontab锁标注的时间,是相互影响的
    //          把定点当做总开关,把周期当做细粒度控制开关,能够更深入的理解和利用crontab
    //      2.  例子
    //          三点五点八点时候每五分钟        * */5 3,5,8 * * *
    
    
    // 每秒报时
    // Timer:支持单位指定 s m h d
    // timer(int: 1s 1s)
    
    // cron:别忘了问号,linux可没有
    timer(cron: */1 * * * * ?)
    when
        eval(true)
    then
        System.out.println(fmt.format(new Date()));
end
  1. 函数(Function)

function提供了一种在规则源文件中插入语义代码的方式,与在普通Java类中不同。他们需要帮助类,否则不能做任何事情。(实际上,编译器会针对这些句子自动产生帮助类。)在规则中使用函数的最主要优点就是你可以把所有逻辑放在一个地方,你可以根据需要更改这些函数的逻辑。函数通常用于在规则的then部分调用某些动作,特别是一些经常被用到的而传入参数不一样的动作。
典型的function格式如下:

function String hello(String name) {
    return "Hello "+name+"!";
}

使用函数:

import function my.package.Foo.hello

rule "using a static function"
when
    eval( true )
then
    System.out.println( hello( "Bob" ) );
end

workbench简介

workbench是drools规则系统的一个系统管理平台,其中包含了一个微版的版本控制器git,一个内置版本的maven,集成了,项目创建,维护,测试,打包,发布一整套流程。

搭建workbench

workbench使用介绍

Drools使用场景

规则引擎虽然非常强大,但并非所有场景都适用。一般来说,规则引擎适用的项目都具有以下一个或多个特征:

  • 需要定义了一个非常复杂的场景,甚至对于业务专家都很难完全定义
  • 没有已知的或定义明确的算法解决方案
  • 有挥发性的要求和需要经常更新
  • 需要快速做出决定,通常是基于部分数据

具体用例

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

推荐阅读更多精彩内容

  • 概述(Overview) 以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规...
    老羊_肖恩阅读 41,696评论 4 31
  • 本文侧重对官方文档的解读及扩展。同时结合自身的实践分享一些自己的见解。请结合官方文档阅读https://docs....
    RyanLee_阅读 13,358评论 4 15
  • 一. 简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的...
    码农梦醒阅读 2,203评论 1 6
  • 规则引擎 相关介绍 规则引擎起源于基于规则的专家系统,而基于规则的专家系统又是专家系统的其中一个分支。专家系统属于...
    xiaolyuh阅读 22,701评论 1 12
  • 昨晚因要拔智齿,牙医帮我打了麻药后,从臀部一直到双脚,一直颤抖,就像寒冷打颤一样,在椅子上躺着持续了大概10分钟,...
    静默你好阅读 1,087评论 0 0