Doorls


参考
https://www.yiibai.com/drools/drools_eclipse_plugin.html#article-start
https://www.cnblogs.com/yjmyzz/p/drools-tutorial.html
http://www.ityouknow.com/drools/2017/08/07/drools-started.html

规则引擎

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

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

Drools

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

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

  • Drools相关概念:
    事实(Fact):对象之间及对象属性之间的关系
    规则(rule):是由条件和结论构成的推理语句,一般表示为if…Then。一个规则的if部分称为LHS,then部分称为RHS。
    模式(module):就是指IF语句的条件。这里IF条件可能是有几个更小的条件组成的大条件。模式就是指的不能在继续分割下去的最小的原子条件。

环境部署

下面是安装Drools插件的先决条件:

如何运行

规则引擎就是避免每次手动修改if else的逻辑分支,通过规则引擎吧UI展示与代码解耦。
解耦后通过规则文件描述符合什么条件的时候,应该去做什么事情;每当规则有变动的时候,只需要修改规则文件,然后重新加载即可生效。

规则文件--drl

drools有专门的规则语法drl,就是专门描述活动的规则是如何执行的

package rules

import com.neo.drools.entity.Order

rule "zero"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout <= 100)
    then
        $s.setScore(0);
        update($s);
end

rule "add100"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 100 && amout <= 500)
    then
        $s.setScore(100);
        update($s);
end

rule "add500"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 500 && amout <= 1000)
    then
        $s.setScore(500);
        update($s);
end

rule "add1000"
    no-loop true
    lock-on-active true
    salience 1
    when
        $s : Order(amout > 1000)
    then
        $s.setScore(1000);
        update($s);
end    

关键词规则

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

语法

全局调度--配置文件kmodule.xml

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

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://www.drools.org/xsd/kmodule">

    <kbase name="point-rulesKB" packages="rules">
        <ksession name="point-rulesKS"/>
    </kbase>

</kmodule>

对配置文件进行说明:

  • Kmodule 中可以包含一个到多个 kbase,分别对应 drl 的规则文件。
  • Kbase 需要一个唯一的 name,可以取任意字符串。
  • packages 为drl文件所在resource目录下的路径。注意区分drl文件中的package与此处的package不一定相同。多个包用逗号分隔。默认情况下会扫描 resources目录下所有(包含子目录)规则文件。
  • kbase的default属性,标示当前KieBase是不是默认的,如果是默认的则不用名称 就可以查找到该 KieBase,但每个 module 最多只能有一个默认 KieBase。
  • kbase 下面可以有一个或多个 ksession,ksession 的 name 属性必须设置,且必须唯一。

前端处理

代码如下

public static final void main(final String[] args) throws Exception{
    KieServices ks = KieServices.Factory.get();
    KieContainer kc = ks.getKieClasspathContainer();
    execute( kc );
}

public static void execute( KieContainer kc ) throws Exception{
    KieSession ksession = kc.newKieSession("point-rulesKS");
    List<Order> orderList = getInitData();
    for (int i = 0; i < orderList.size(); i++) {
        Order o = orderList.get(i);
        ksession.insert(o);
        ksession.fireAllRules();
        addScore(o);
    }
    ksession.dispose();
}

代码解释:首先通过请求获取 KieServices,通过KieServices获取KieContainer,KieContainer加载规则文件并获取KieSession,KieSession来执行规则引擎,KieSession是一个轻量级组建,每次执行完销毁。KieContainer是重量级组建可以考虑复用。

应用拓展

excel生成规则


下面来解释一下每一行都什么意思
表示规则属于哪个包下的,类似于java中的 package
规则在处理逻辑时用到的类,多个的话,在后面用逗号隔开
一些共用方法可以通过 Functions 来定义,跟java中的方法差不多,就是把 public 换成了 function
空行,必须要有的
给这个excel里的规则定义一个名字,方便别人查看
从这一行开始下面就是规则的部分了,这一行相当于表头,标注了每一列都是什么意思,固定写法,其中 CONDITION 可以有多个
这一行是初始化对象的
指定条件以及输出的处理方式
这一行开始就是真实的业务逻辑了,CONDITION 下的是条件,ACTION 下的是结果,我这给这一行也定成了表头并起了相应的名字,如果不想定表头的话,这一行要为空行
第一列是规则名,第二列是条件,第三列是结果

读取Excel生成规则文件

//把excel翻译成drl文件
@Test
public void test2() {
    SpreadsheetCompiler compiler = new SpreadsheetCompiler();
    // 最后一个参数是excel里 sheet 的名称
    String rules = compiler.compile(ResourceFactory.newClassPathResource("rules" + File.separator + "rule.xlsx", "UTF-8"), "Sheet1");

    try {
        BufferedWriter out = new BufferedWriter(new FileWriter("src/main/resources/rules/test-rule-excel.drl"));
        out.write(rules);
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

上面excel里的规则生成的文件内容如下

package com.example.demo;
//generated from Decision Table
import com.example.drools.Demo;
function int count(Demo $demo) {
    return $demo.getA() + $demo.getB() + $demo.getC();
}
// rule values at A10, header at A5
rule "条件计算1"
    when
        $demo:Demo(a>3,b>4)
    then
        $demo.setTotal(count($demo));
end

// rule values at A11, header at A5
rule "条件计算2"
    when
        $demo:Demo(c<3)
    then
        $demo.setTotal($demo.getA() + $demo.getB());
end

直接读取Excel决策表处理业务规则

上面介绍了读取excel生成rule文件,然后再通过读取规则文件来处理业务,这样比较麻烦,下面来介绍一下直接读取excel,然后处理业务逻辑
代码如下

//读取excel规则处理逻辑
@Test
public void test1() {
    KieServices kieServices = KieServices.Factory.get();
    Resource dt = ResourceFactory.newClassPathResource("rules/rule.xlsx", getClass());
    KieFileSystem kieFileSystem = kieServices.newKieFileSystem().write(dt);
    KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
    kieBuilder.buildAll();
    KieModule kieModule = kieBuilder.getKieModule();
    KieSession kieSession = kieServices.newKieContainer(kieModule.getReleaseId()).newKieSession();

    Demo demo = new Demo();
    demo.setA(6);
    demo.setB(5);
    demo.setC(4);

    kieSession.insert(demo);
    int count = kieSession.fireAllRules();
    System.out.println("总共触发了: " + count + " 条规则");
    System.out.println(demo);
}

总共触发了: 1 条规则

Demo{a=6, b=5, c=4, total=15, errorMsg=[]}

总结
jboss还提供了一个网站,能直接在网页上配置出来规则,更加方便了,不过对于程序员来说,写drl文件应该是首选,对于业务人员写excel应该是首选

PHP与规则引擎

php没有太多的经典规则引擎,可以参考https://github.com/tonera/Rules

posted @ 2020-09-30 16:22  Alice1005  阅读(281)  评论(0编辑  收藏  举报