• 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

  • 相关阅读:
    配置变量的信息
    Smarty保留变量信息
    选择排序
    java.utils.HashMap数据结构分析
    HashMap的工作原理
    Dubbo
    五种单例模式:
    Redis的持久化机制包括RBD和AOF两种,对于这两种持久化方式各有优势
    Zookeeper要安装在奇数个节点,但是为什么?
    Redis搭建多台哨兵
  • 原文地址:https://www.cnblogs.com/Alice1005/p/13755157.html
Copyright © 2020-2023  润新知