规则引擎之Drools - Go语言中文社区

规则引擎之Drools


一、什么是Drools?
Drools 是一个基于Charles Forgy’s的RETE算法的,易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。
业务分析师人员或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业务规则。
Drools 是用Java语言编写的开放源码规则引擎,使用Rete算法对所编写的规则求值。Drools允许使用声明方式表达业务逻辑。可以使用非XML的本地语言编写规则,从而便于学习和理解。并且,还可以将Java代码直接嵌入到规则文件中,这令Drools的学习更加吸引人。
二、规则引擎有什么作用?
比如:一天老板想弄一个活动营销,体验语音识别转账,选择这个时间段多少人进行抽奖,然后就开始写业务逻辑,先查询,然后进行随机筛选,但是,如果领导体验了,必须让领导中奖,本来想法是好的,突然,体验人数不够,或者超了,但是中奖名额就那么多,然后改粒度,本来在100个人抽10个,但是现在改成1000个人抽10个,进行打包上传到服务器上,但是开放人员学聪明了,将数据放到数据库中,但是老板说,下一次要变一下规则,添加红包,或者代金券之类的,这样又要开发部署,然后就有了规则引擎,将业务代码抽取去出来,改成配置文件编写的代码,类似这样,
在这里插入图片描述
规则引擎作用,开发者不需要管理业务逻辑,进行开发,产品完成之后,然后将业务规则,变成可以动态处理,随时改变的规则引擎,如果开发者不想自己操作,可以开发一种可视化的拖拽式的操作界面,然后生成规则引擎,或者文档,表格或者.drl的等可读性代码文件。将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策

三、怎么实现动态规则引擎?
采用Drools+springboot进行开发规则引擎实现。
1.先从数据库获取规则 getActivityRuleList()
2.再跟据获取的规则生成drt可以解析的map型data prepareData(ruleDTO)
3.通过drt解析,生成drl规则string objectDataCompiler.compile(Arrays.asList(data), Thread.currentThread().getContextClassLoader().getResourceAsStream(“give-reward-rule-template.drt”));
4.根据以上获得的规则string生成maven结构的规则并加载 createOrRefreshDrlInMemory(ruleDrls)
四、案例
采用springboot2.1.X与drools7.11.X以上版本
在这里插入图片描述pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.citydo</groupId>
    <artifactId>springboot_drools</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot_drools</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <drools.version>7.11.0.Final</drools.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${drools.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-tx</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${drools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.flink</groupId>
            <artifactId>flink-shaded-hive</artifactId>
            <version>6.0-flink</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Message.java

package com.citydo.springboot_drools.model;

public class Message {
    public static int HELLO = 0;
    public static int GOODBYE = 1;
    private String message;
    private int status;

    public String getMessage() {
        return message;
    }

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

    public int getStatus() {
        return status;
    }

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

}

kmodule.xml

<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--package是文件目录-->
    <kbase name="rules" packages="rules,myrules">
        <ksession name="ksession-rule"/>
    </kbase>
    <!--<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">-->
    <!--这玩意一定要放在META-INF里面-->
    <!--name kbase的唯一标志
    packages 路径必须正确可少写可多写可不写
    不写的话放于根目录(不建议)
    ksession 的唯一标记-->
    <!--<kbase name="rules" packages="Drools.rules">-->
    <!--<kbase name="rules" packages="rules">-->
        <!--<kbase name="rules" packages="">-->
        <!--<kbase name="rules" packages="myrules">-->
        <!--默认用最后一个-->
        <!--<kbase name="rules" packages="rules,myrules">-->
  <!--      <ksession name="ksession-rules"/>
    </kbase>-->
</kmodule>

Sample.drl

package com.sample.myrules
//package 随便写,但是不可重名

import com.citydo.springboot_drools.model.Message
 
rule "Hello World"
    when
        $m : Message( status == Message.HELLO, $myMessage : message )
    then
        System.out.println( "rules.sample.drl begin1" );
        System.out.println( $myMessage);
        $m.setMessage( "Goodbye world1" );
        $m.setStatus( Message.GOODBYE );
        update( $m );
        System.out.println( "rules.sample.drl end1" );
end

DroolsTest.java

package com.citydo.springboot_drools;


import com.citydo.springboot_drools.model.Message;
import com.citydo.springboot_drools.utils.DroolsUtil;
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-rule");
            KieSession ksession = DroolsUtil.getKieSessionByName("ksession-rule");
            //KieSession kSession = kContainer.newKieSession();

            // go !
            Message message = new Message();
            message.setMessage("Hello World");
            message.setStatus(Message.HELLO);

            ksession.insert(message);
            ksession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

}

DroolsUtils

package com.citydo.springboot_drools.utils;

import org.kie.api.KieServices;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DroolsUtil {
    public static final Logger log = LoggerFactory.getLogger(DroolsUtil.class);

    /**
     * 线程安全单例
     */
    private static volatile KieServices kieServices = KieServices.Factory.get();
    /**
     * KieBase容器,线程安全单例
     */
    private static volatile KieContainer kieContainer;

    /**
     * 加载KieContainer容器
     */
    public static KieContainer loadKieContainer() throws RuntimeException {
        //通过kmodule.xml 找到规则文件,这个文件默认放在resources/META-INF文件夹
        log.info("准备创建 KieContainer");

        if (kieContainer == null) {
            log.info("首次创建:KieContainer");
            // 设置drools的日期格式
            System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
            //线程安全
            synchronized (DroolsUtil.class) {
                if (kieContainer == null) {
                    // 创建Container
                    kieContainer = kieServices.getKieClasspathContainer();
                    // 检查规则文件是否有错
                    Results results = kieContainer.verify();
                    if (results.hasMessages(Message.Level.ERROR)) {
                        StringBuffer sb = new StringBuffer();
                        for (Message mes : results.getMessages()) {
                            sb.append("解析错误的规则:").append(mes.getPath()).append(" 错误位置:").append(mes.getLine()).append(";");
                        }
                        throw new RuntimeException(sb.toString());
                    }
                }
            }

        }
        log.info("KieContainer创建完毕");
        return kieContainer;
    }

    /**
     * 根据kiesession 名称创建KieSession ,每次调用都是一个新的KieSession
     * @param name kiesession的名称
     * @return 一个新的KieSession,每次使用后要销毁
     */
    public static KieSession getKieSessionByName(String name) {
        if (kieContainer == null) {
            kieContainer = loadKieContainer();
        }
        KieSession kieSession;
        try {
            kieSession = kieContainer.newKieSession(name);
        } catch (Exception e) {
            log.error("根据名称:" + name + " 创建kiesession异常");
            throw new RuntimeException(e);
        }
        return kieSession;
    }

}

五、规则引擎有哪些?
java开源的规则引擎有:Drools、Easy Rules、Mandarax、IBM ILOG。使用最为广泛并且开源的是Drools。
参考:http://www.cnblogs.com/ydymz/p/9590245.html
参考:https://www.imooc.com/article/25976
参考:https://www.jianshu.com/p/e713860b128e

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_32447301/article/details/89084422
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-27 15:33:32
  • 阅读 ( 2141 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢