一.前言

网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践,并提供源代码,供大家参考

二.设计思路及具体代码

    首先我希望是轻量级的使用drools,不希望使用太过复杂的架构,以这种思路入手,就可以与任何项目轻易融入,这样就需要能够将drools规则的来源,从规则文件(drl)中可以从maven和自己的数据库中获取,脚本是动态的,配合drools6.5支持通过maven接入的规则的API,就可以做到从任何处获取规则内容

一个工具类DroolsUtils


  1. package com.vip.jie.rule.util;
  2. import org.drools.compiler.kie.builder.impl.InternalKieModule;
  3. import org.kie.api.KieServices;
  4. import org.kie.api.builder.KieBuilder;
  5. import org.kie.api.builder.KieFileSystem;
  6. import org.kie.api.builder.ReleaseId;
  7. import org.kie.api.builder.model.KieBaseModel;
  8. import org.kie.api.builder.model.KieModuleModel;
  9. import org.kie.api.builder.model.KieSessionModel;
  10. import org.kie.api.conf.EqualityBehaviorOption;
  11. import org.kie.api.conf.EventProcessingOption;
  12. import java.io.IOException;
  13. /**
  14. * 动态生成kjar
  15. * @author jie01.zhu
  16. * @DateTime 2018/3/19 22:14
  17. */
  18. public class DroolsUtils {
  19. /**
  20. * 创建默认的kbase和stateful的kiesession
  21. *
  22. * @param ks
  23. * @param isdefault
  24. * @return
  25. */
  26. private static KieFileSystem createKieFileSystemWithKProject(KieServices ks, boolean isdefault) {
  27. KieModuleModel kproj = ks.newKieModuleModel();
  28. KieBaseModel kieBaseModel1 = kproj.newKieBaseModel("KBase").setDefault(isdefault)
  29. .setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
  30. .setEventProcessingMode(EventProcessingOption.STREAM);
  31. // Configure the KieSession.
  32. kieBaseModel1.newKieSessionModel("KSession").setDefault(isdefault)
  33. .setType(KieSessionModel.KieSessionType.STATEFUL);
  34. KieFileSystem kfs = ks.newKieFileSystem();
  35. kfs.writeKModuleXML(kproj.toXML());
  36. return kfs;
  37. }
  38. /**
  39. * 创建kjar的pom
  40. *
  41. * @param releaseId
  42. * @param dependencies
  43. * @return
  44. */
  45. private static String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
  46. String pom = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  47. + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
  48. + " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n"
  49. + " <modelVersion>4.0.0</modelVersion>\n" + "\n" + " <groupId>" + releaseId.getGroupId()
  50. + "</groupId>\n" + " <artifactId>" + releaseId.getArtifactId() + "</artifactId>\n" + " <version>"
  51. + releaseId.getVersion() + "</version>\n" + "\n";
  52. if (dependencies != null && dependencies.length > 0) {
  53. pom += "<dependencies>\n";
  54. for (ReleaseId dep : dependencies) {
  55. pom += "<dependency>\n";
  56. pom += " <groupId>" + dep.getGroupId() + "</groupId>\n";
  57. pom += " <artifactId>" + dep.getArtifactId() + "</artifactId>\n";
  58. pom += " <version>" + dep.getVersion() + "</version>\n";
  59. pom += "</dependency>\n";
  60. }
  61. pom += "</dependencies>\n";
  62. }
  63. pom += "</project>";
  64. return pom;
  65. }
  66. /**
  67. * 初始化一个kjar:把原有的drl包含进新建的kjar中
  68. *
  69. * @param ks
  70. * @param releaseId
  71. * @return
  72. * @throws IOException
  73. */
  74. public static InternalKieModule initKieJar(KieServices ks, ReleaseId releaseId) throws IOException {
  75. KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
  76. kfs.writePomXML(getPom(releaseId));
  77. KieBuilder kieBuilder = ks.newKieBuilder(kfs);
  78. if (!kieBuilder.buildAll().getResults().getMessages().isEmpty()) {
  79. throw new IllegalStateException("Error creating KieBuilder.");
  80. }
  81. return (InternalKieModule) kieBuilder.getKieModule();
  82. }
  83. public static InternalKieModule createKieJar(KieServices ks, ReleaseId releaseId, DroolsResource droolsResource) {
  84. KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
  85. kfs.writePomXML(getPom(releaseId));
  86. kfs.write("src/main/resources/" + droolsResource.getTargetResourceName(), droolsResource.getResource());
  87. KieBuilder kieBuilder = ks.newKieBuilder(kfs);
  88. if (!kieBuilder.getResults().getMessages().isEmpty()) {
  89. throw new IllegalStateException(
  90. "Error creating KieBuilder. errorMsg:" + kieBuilder.getResults().getMessages());
  91. }
  92. return (InternalKieModule) kieBuilder.getKieModule();
  93. }
  94. }

重点调用参考:


  1. String fileName = "jie-" + group + "-rules";
  2. /**
  3.  * 指定kjar包
  4.  */
  5. final ReleaseId releaseId = kieServices.newReleaseId("com.vip.jie", fileName, "1.0.0");
  6. log.info("DroolsGetKieSession fileName:{}", fileName);
  7. log.info("[DroolsGetKieSession] drlStr:{}", drlStr);
  8. // 创建初始化的kjar
  9. InternalKieModule kJar = DroolsUtils.createKieJar(kieServices, releaseId,
  10. new DroolsResource(ResourceFactory.newByteArrayResource(drlStr.getBytes()),
  11. fileName + ".drl"));

其次再将如何让使用者可以很灵活的接入,利用可变参数类型,将入参对象无限制传入,由规则脚本去决定入参的变化,通过此种方式可以比较好的实现业务灵活接入

如下单元测试类:


  1. package com.vip.jie.rule.service.impl;
  2. import com.vip.jie.rule.object.User;
  3. import com.vip.jie.rule.service.RuleManager;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.junit.Test;
  6. import static junit.framework.TestCase.fail;
  7. /**
  8. * 规则测试
  9. * @author jie01.zhu
  10. * @DateTime 2018/3/19 21:17
  11. *
  12. */
  13. @Slf4j
  14. public class RuleManagerImplTest {
  15. private RuleManager ruleManager = new RuleManagerImpl();
  16. private String getRuleContent() {
  17. StringBuilder stringBuilder = new StringBuilder();
  18. stringBuilder.append("import com.vip.jie.rule.object.User;\n");
  19. stringBuilder.append("rule test1 when\n");
  20. stringBuilder.append("user : User(age==20)\n");
  21. stringBuilder.append("then\n");
  22. stringBuilder.append("user.setName(\"张三\");\n");
  23. stringBuilder.append("end\n");
  24. return stringBuilder.toString();
  25. }
  26. @Test
  27. public void executeRule1() throws Exception {
  28. User user = new User();
  29. user.setAge(20);
  30. //调用规则
  31. ruleManager.executeRule("test1", getRuleContent(), user);
  32. log.info("test result:{}", user.toString());
  33. if (!"张三".equals(user.getName())) {
  34. fail("error rule");
  35. }
  36. }
  37. @Test
  38. public void executeRule2() throws Exception {
  39. User user = new User();
  40. user.setAge(21);
  41. //调用规则
  42. ruleManager.executeRule("test1", getRuleContent(), user);
  43. log.info("test result:{}", user.toString());
  44. if ("张三".equals(user.getName())) {
  45. fail("error rule");
  46. }
  47. }
  48. }

三.对应示例源代码获取方式

githup:

https://github.com/jie01/drools-demo

csdn资源下载地址:

https://download.csdn.net/download/vipshop_fin_dev/10296393


还有一些关于安全性及与spring的封装思路,作者表示还会继续完善,并还不是最终版本,有需要可以持续关注-_-!

与当前文章有关联的链接

业务框架之个性化监控方案


vipshop_ebs/朱杰

2018-03-19

原文地址:https://blog.csdn.net/vipshop_fin_dev/article/details/79618067

规则引擎drools封装的更多相关文章

  1. 开源规则引擎 drools

    java语言开发的开源业务规则引擎 DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用 ...

  2. 开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule

    直接进入正题 我们在使用开源规则引擎 Drools 的时候, 启动的时候可能会抛出如下异常: Caused by: java.lang.ClassCastException: cn.com.cheng ...

  3. [Drools]JAVA规则引擎 -- Drools 2

    上一篇文章 http://blog.csdn.net/quzishen/archive/2011/01/25/6163012.aspx 描述了一些常用的drools的语法标签和一个模拟实例即发送积分的 ...

  4. 使用规则引擎Drools计算圆周率PI

    实际上是使用规则引擎能够更新工作内存区重新匹配规则实现迭代功能. 使用了策略模式实现. <规则引擎与RETE算法介绍> PPT : http://files.cnblogs.com/lov ...

  5. JAVA规则引擎 -- Drools

    Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  6. [Drools]JAVA规则引擎 -- Drools

    Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  7. 小明历险记:规则引擎drools教程一

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

  8. 规则引擎 drools

    https://www.jianshu.com/p/725811f420db 深入了解Drools 简单介绍 笔者正在做风控系统,风控系统里边存在非常多的规则(比如:age < 16 || ag ...

  9. 规则引擎drools的简单使用

    规则引擎适用于有复杂多变的规则,如商品满减.积分赠送.考勤规则等 一.引入maven依赖 <dependency> <groupId>org.drools</groupI ...

随机推荐

  1. nginx之旅(第三篇):代理、正向代理、反向代理、代理的原理、nginx反向代理场景、nginx反向代理配置、nginx反向代理语法

    一.代理服务与反向代理 什么是代理服务 代理-代理办理(代理理财.代理收货.代理购物等等). 一般情况下,如果没有特别说明,代理技术默认说的是正向代理技术.关于正向代理的概念如下: 正向代理(forw ...

  2. TCP 通信时序及状态变迁

    TCP 通信时序及状态变迁 参考链接: https://www.cnblogs.com/boxker/p/11214886.html https://blog.csdn.net/miss_ruoche ...

  3. 逆向破解之160个CrackMe —— 031

    CrackMe —— 031 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  4. vue - 基础(3)

    1.数据的双向绑定 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  5. activiti 工作流动态设置指定节点任务人、责任人、组的实现方式

    首先给大家看一下我的流程图: 流程文件leaveBill.bpmn <?xml version="1.0" encoding="UTF-8"?>&l ...

  6. Win10开启快速启动后关机变重启

    同样可以用来解决,“msconfig引导为空”,“默认操作系统为空”,“win10改为uefi启动后关机变重启”,“legacy转uefi后无法关机” 问题起因 换完主板和cpu后,新的主板在开机时总 ...

  7. 仿照手机写一个WIFI的操作程序

    本篇博客仿照手机的功能,写一个WIFI的操作程序. 手机的WIFI功能有哪些呢?当我们进入wlan的设置界面的时候,将自动识别出若干个wifi的热点,并且会自动更新,当点击某个wifi热点的时候,然后 ...

  8. Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value 'Öйú±ê׼ʱ¼ä'

    java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more ...

  9. Django 缓存配置的多种方式

    django 的缓存配置有多种方式,主要包含以下几种: 1.开发调试模式 2.内存模式 3.使用文件 4.直接使用数据库 5.使用redis或者memcache 这里主要是记录一下那些不常用,但是在微 ...

  10. 11-赵志勇机器学习-DBSCAN聚类

    (草稿) 两点关系的三种定义: 1. 直接密度可达:A在B的邻域内: 2. 密度可达:AB之间存在,直接密度可达的点串: 3. 密度连接:AB之间存在点k,使得Ak和Bk都密度可达: 过程: 1. 对 ...