规则引擎之Drools

缺乏、安全感 2022-02-23 12:57 1409阅读 0赞

一、什么是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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1.4.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.citydo</groupId>
  12. <artifactId>springboot_drools</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>springboot_drools</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. <drools.version>7.11.0.Final</drools.version>
  19. </properties>
  20. <dependencies>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-test</artifactId>
  28. <scope>test</scope>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-autoconfigure</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.kie</groupId>
  36. <artifactId>kie-spring</artifactId>
  37. <version>${drools.version}</version>
  38. <exclusions>
  39. <exclusion>
  40. <groupId>org.springframework</groupId>
  41. <artifactId>spring-tx</artifactId>
  42. </exclusion>
  43. <exclusion>
  44. <groupId>org.springframework</groupId>
  45. <artifactId>spring-beans</artifactId>
  46. </exclusion>
  47. <exclusion>
  48. <groupId>org.springframework</groupId>
  49. <artifactId>spring-core</artifactId>
  50. </exclusion>
  51. <exclusion>
  52. <groupId>org.springframework</groupId>
  53. <artifactId>spring-context</artifactId>
  54. </exclusion>
  55. </exclusions>
  56. </dependency>
  57. <dependency>
  58. <groupId>org.drools</groupId>
  59. <artifactId>drools-compiler</artifactId>
  60. <version>${drools.version}</version>
  61. </dependency>
  62. <dependency>
  63. <groupId>org.projectlombok</groupId>
  64. <artifactId>lombok</artifactId>
  65. <version>1.18.4</version>
  66. </dependency>
  67. <dependency>
  68. <groupId>com.alibaba.flink</groupId>
  69. <artifactId>flink-shaded-hive</artifactId>
  70. <version>6.0-flink</version>
  71. </dependency>
  72. </dependencies>
  73. <build>
  74. <plugins>
  75. <plugin>
  76. <groupId>org.springframework.boot</groupId>
  77. <artifactId>spring-boot-maven-plugin</artifactId>
  78. </plugin>
  79. </plugins>
  80. </build>
  81. </project>

Message.java

  1. package com.citydo.springboot_drools.model;
  2. public class Message {
  3. public static int HELLO = 0;
  4. public static int GOODBYE = 1;
  5. private String message;
  6. private int status;
  7. public String getMessage() {
  8. return message;
  9. }
  10. public void setMessage(String message) {
  11. this.message = message;
  12. }
  13. public int getStatus() {
  14. return status;
  15. }
  16. public void setStatus(int status) {
  17. this.status = status;
  18. }
  19. }

kmodule.xml

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

Sample.drl

  1. package com.sample.myrules
  2. //package 随便写,但是不可重名
  3. import com.citydo.springboot_drools.model.Message
  4. rule "Hello World"
  5. when
  6. $m : Message( status == Message.HELLO, $myMessage : message )
  7. then
  8. System.out.println( "rules.sample.drl begin1" );
  9. System.out.println( $myMessage);
  10. $m.setMessage( "Goodbye world1" );
  11. $m.setStatus( Message.GOODBYE );
  12. update( $m );
  13. System.out.println( "rules.sample.drl end1" );
  14. end

DroolsTest.java

  1. package com.citydo.springboot_drools;
  2. import com.citydo.springboot_drools.model.Message;
  3. import com.citydo.springboot_drools.utils.DroolsUtil;
  4. import org.kie.api.KieServices;
  5. import org.kie.api.runtime.KieContainer;
  6. import org.kie.api.runtime.KieSession;
  7. public class DroolsTest {
  8. public static final void main(String[] args) {
  9. try {
  10. // load up the knowledge base
  11. KieServices ks = KieServices.Factory.get();
  12. KieContainer kContainer = ks.getKieClasspathContainer();
  13. //KieSession kSession = kContainer.newKieSession("ksession-rule");
  14. KieSession ksession = DroolsUtil.getKieSessionByName("ksession-rule");
  15. //KieSession kSession = kContainer.newKieSession();
  16. // go !
  17. Message message = new Message();
  18. message.setMessage("Hello World");
  19. message.setStatus(Message.HELLO);
  20. ksession.insert(message);
  21. ksession.fireAllRules();
  22. } catch (Throwable t) {
  23. t.printStackTrace();
  24. }
  25. }
  26. }

DroolsUtils

  1. package com.citydo.springboot_drools.utils;
  2. import org.kie.api.KieServices;
  3. import org.kie.api.builder.Message;
  4. import org.kie.api.builder.Results;
  5. import org.kie.api.runtime.KieContainer;
  6. import org.kie.api.runtime.KieSession;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. public class DroolsUtil {
  10. public static final Logger log = LoggerFactory.getLogger(DroolsUtil.class);
  11. /**
  12. * 线程安全单例
  13. */
  14. private static volatile KieServices kieServices = KieServices.Factory.get();
  15. /**
  16. * KieBase容器,线程安全单例
  17. */
  18. private static volatile KieContainer kieContainer;
  19. /**
  20. * 加载KieContainer容器
  21. */
  22. public static KieContainer loadKieContainer() throws RuntimeException {
  23. //通过kmodule.xml 找到规则文件,这个文件默认放在resources/META-INF文件夹
  24. log.info("准备创建 KieContainer");
  25. if (kieContainer == null) {
  26. log.info("首次创建:KieContainer");
  27. // 设置drools的日期格式
  28. System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
  29. //线程安全
  30. synchronized (DroolsUtil.class) {
  31. if (kieContainer == null) {
  32. // 创建Container
  33. kieContainer = kieServices.getKieClasspathContainer();
  34. // 检查规则文件是否有错
  35. Results results = kieContainer.verify();
  36. if (results.hasMessages(Message.Level.ERROR)) {
  37. StringBuffer sb = new StringBuffer();
  38. for (Message mes : results.getMessages()) {
  39. sb.append("解析错误的规则:").append(mes.getPath()).append(" 错误位置:").append(mes.getLine()).append(";");
  40. }
  41. throw new RuntimeException(sb.toString());
  42. }
  43. }
  44. }
  45. }
  46. log.info("KieContainer创建完毕");
  47. return kieContainer;
  48. }
  49. /**
  50. * 根据kiesession 名称创建KieSession ,每次调用都是一个新的KieSession
  51. * @param name kiesession的名称
  52. * @return 一个新的KieSession,每次使用后要销毁
  53. */
  54. public static KieSession getKieSessionByName(String name) {
  55. if (kieContainer == null) {
  56. kieContainer = loadKieContainer();
  57. }
  58. KieSession kieSession;
  59. try {
  60. kieSession = kieContainer.newKieSession(name);
  61. } catch (Exception e) {
  62. log.error("根据名称:" + name + " 创建kiesession异常");
  63. throw new RuntimeException(e);
  64. }
  65. return kieSession;
  66. }
  67. }

五、规则引擎有哪些?
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

发表评论

表情:
评论列表 (有 0 条评论,1409人围观)

还没有评论,来说两句吧...

相关阅读

    相关 规则引擎drools封装

    一.前言     网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对

    相关 开源规则引擎 drools

    前言 在很多企业的 IT 业务系统中,经常会有大量的业务规则配置,而且随着企业管理者的决策变化,这些业务规则也会随之发生更改。为了适应这样的需求,我们的 IT 业务系统应

    相关 规则引擎drools

    小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看。 小明的烦恼

    相关 Drools规则引擎

    规则引擎 工作中业务要求对保养手册计算规则,有机会认识了Drools这款强大功能的工具。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5