drools规则引擎

项目链接

现状:

  1. 运维同学(各种同学)通过后台管理界面直接配置相关规则,这里是通过输入框、下拉框等完成输入的,非常简单;
  2. 规则配置完毕后,前端请求后端,此时服务端根据参数(即规则)生成drl规则文件;
  3. 用户侧有相关请求到达时,服务端加载规则文件(可能是多个,一般一个广告、活动对应一个规则文件),并通过引擎去检查当前用户各种状态是否满足规则文件;
  4. 将所有满足的规则文件对应的广告、活动进行下发,同时更新用户数据;
  5. 完成整个drools相关流程;

关于

drools是一款标准、效率高、速度快的开源规则引擎,基于ReteOO算法,目前主要应用场景在广告、活动下发等领域非常多,比如APP的活动下发,通常都是有很多条件限制的,且各种活动层出不穷,无法代码穷举,而如果每次为了一个活动重新发版上线,显然是不合理的,因此通过drools将活动中变的部分抽象为一个个单独的规则文件,来屏蔽这部分的变化,使得系统不需要从代码层面做出改变,当然了为了更加极致的抽象,通常还需要对规则中的一些可配条件(大于、小于、等于、范围、次数等)也提取到数据库中,这样在现有规则不满足要求时,可以直接通过更改数据库的对应规则表来完善,同样不需要改代码;

我们当时的需求主要就是广告、活动下发规则比较多,广告也是各式各样,因此去调研了drools,对drools也没有过多的挖掘其更多特性,因此还需要大家的指点;

drools简单使用

服务端项目中使用drools的几个基本步骤;

step 1 -- 添加相关依赖到maven pom.xml

  1. <dependency>
  2. <groupId>org.drools</groupId>
  3. <artifactId>drools-core</artifactId>
  4. <version>6.4.0.Final</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.drools</groupId>
  8. <artifactId>drools-compiler</artifactId>
  9. <version>6.4.0.Final</version>
  10. </dependency>

step 2 -- 创建实体类加载规则文件

  1. public class CarIllegalRules extends BaseRules{
  2. public static void main(String[] args) {
  3. try {
  4. KieServices ks = KieServices.Factory.get();
  5. KieContainer kContainer = ks.getKieClasspathContainer();
  6. KieSession ksession = kContainer.newKieSession("ksession-rules");
  7. CarIllegalRules carIllegalRules = new CarIllegalRules(10,500,10);
  8. ksession.insert(carIllegalRules);
  9. ksession.fireAllRules();
  10. System.out.println(carIllegalRules.isCan_push()+","+carIllegalRules.getContent());
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. private int illegal_count;
  16. private int illegal_money;
  17. private int illegal_points;
  18. public CarIllegalRules(int illegal_count, int illegal_money, int illegal_points) {
  19. super();
  20. this.illegal_count = illegal_count;
  21. this.illegal_money = illegal_money;
  22. this.illegal_points = illegal_points;
  23. this.param_value = "illegal_count,illegal_money,illegal_points";
  24. }
  25. @Override
  26. public String toString() {
  27. return "CarIllegalRules [illegal_count=" + illegal_count + ", illegal_money=" + illegal_money
  28. + ", illegal_points=" + illegal_points + ", can_push=" + can_push + ", content=" + content + ", tts="
  29. + tts + "]";
  30. }
  31. public int getIllegal_count() {
  32. return illegal_count;
  33. }
  34. public void setIllegal_count(int illegal_count) {
  35. this.illegal_count = illegal_count;
  36. }
  37. public int getIllegal_money() {
  38. return illegal_money;
  39. }
  40. public void setIllegal_money(int illegal_money) {
  41. this.illegal_money = illegal_money;
  42. }
  43. public int getIllegal_points() {
  44. return illegal_points;
  45. }
  46. public void setIllegal_points(int illegal_points) {
  47. this.illegal_points = illegal_points;
  48. }
  49. }

PS:main函数是用来测试这个类的;

step 3 -- 创建DSLUtils类去执行相应规则

  1. public class DSLUtil {
  2. public static void fireRules(File file, Object rules) {
  3. try {
  4. KieServices kieServices = KieServices.Factory.get();
  5. KieFileSystem kfs = kieServices.newKieFileSystem();
  6. Resource resource = kieServices.getResources().newFileSystemResource(file);
  7. fire(rules, kieServices, kfs, resource);
  8. } catch (Exception e) {
  9. e.printStackTrace();
  10. }
  11. }
  12. public static void fireRules(String urlStr, Object rules) {
  13. try {
  14. KieServices kieServices = KieServices.Factory.get();
  15. KieFileSystem kfs = kieServices.newKieFileSystem();
  16. Resource resource = kieServices.getResources().newFileSystemResource(FileUtil.getFileFromUrl(urlStr));
  17. fire(rules, kieServices, kfs, resource);
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. private static void fire(Object commonRules, KieServices kieServices, KieFileSystem kfs, Resource resource)
  23. throws Exception {
  24. resource.setResourceType(ResourceType.DRL);
  25. kfs.write(resource);
  26. KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
  27. if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) {
  28. throw new Exception();
  29. }
  30. KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
  31. KieBase kBase = kieContainer.getKieBase();
  32. KieSession ksession = kBase.newKieSession();
  33. ksession.insert(commonRules);
  34. ksession.fireAllRules();
  35. }
  36. }

step 4 -- 创建一个类去生成规则文件

比如生成 music.drl 的音乐规则文件,这一步是可选的,区别在于规则文件的生成是代码生成,还是人工生成,我们的项目中是运维同学在后台管理界面通过一些图形化输入框输入一些指定参数,而生成规则文件是服务端代码生成的,因此有了这部分,比较实用,一方面可以降低生成规则文件的门槛,任何人都可以做,另一方面也避免了人工出错的可能;

  1. public class ActivityUtil {
  2. /**
  3. * rule template string
  4. */
  5. private static String template =
  6. "package com.aispeech.dsl\r\n\r\n" +
  7. "import {entity_package_path};\r\n\r\n" +
  8. "import {entity_package_path}.*;\r\n\r\n" +
  9. "rule \"{rule_name}\"\r\n\r\n" +
  10. "when\r\n" +
  11. "\t{instance_name}:{class_name}({rules})\r\n" +
  12. "then\r\n" +
  13. "\t{do}\r\n" +
  14. "end";
  15. private static final String AND = " && ";
  16. private static final String OR = " || ";
  17. /**
  18. * get business rule file xxx.drl
  19. * @param carActivity user info entity
  20. * @param clazz entity class
  21. * @return
  22. */
  23. public static File createBusinessRuleFile(Car_activity carActivity, Class clazz, String[] param_texts, String[] param_values) {
  24. String ruleStr = template;
  25. String entity_package_path = (clazz+"").substring(6);
  26. String rule_name = "rule_"+carActivity.getId();
  27. String class_name = (clazz+"").substring((clazz+"").lastIndexOf(".")+1);
  28. String instance_name = class_name.toLowerCase();
  29. String rules = "";
  30. JSONArray conditionArray = JSONArray.parseArray(carActivity.getAim_condition());
  31. for(int i=0;i<conditionArray.size();i++) {
  32. JSONObject condition = conditionArray.getJSONObject(i);
  33. rules += "\r\n\t\t("+condition.getString("param")+condition.getString("operator")+condition.getString("value")+")" + AND;
  34. }
  35. rules = rules.length()>0?rules.substring(0, rules.lastIndexOf(AND)):rules;
  36. for (String param_value : param_values) {
  37. rules += "\r\n\t\t,"+param_value.toLowerCase()+":"+param_value;
  38. }
  39. String content = JSONObject.parseObject(carActivity.getContent()).getString("content");
  40. String tts = carActivity.getTts();
  41. for (int i=0;i<param_texts.length;i++) {
  42. content = content.replace("#"+param_texts[i]+"#", "\"+"+param_values[i]+"+\"");
  43. tts = tts.replace("#"+param_texts[i]+"#", "\"+"+param_values[i]+"+\"");
  44. }
  45. String _do = instance_name+".setCan_push(true);";
  46. _do += "\r\n\t" + instance_name+".setContent(\""+content+"\");";
  47. _do += "\r\n\t" + instance_name+".setTts(\""+tts+"\");";
  48. return returnFile(ruleStr, entity_package_path, rule_name, class_name, instance_name, _do, rules);
  49. }
  50. /**
  51. * @param ruleStr
  52. * @param entity_package_path
  53. * @param rule_name
  54. * @param class_name
  55. * @param instance_name
  56. * @param _do
  57. * @param rules
  58. * @return
  59. */
  60. private static File returnFile(String ruleStr, String entity_package_path, String rule_name, String class_name,
  61. String instance_name, String _do, String rules) {
  62. ruleStr = ruleStr.replace("{entity_package_path}", entity_package_path)
  63. .replace("{rule_name}", rule_name)
  64. .replace("{class_name}", class_name)
  65. .replace("{instance_name}", instance_name)
  66. .replace("{do}", _do)
  67. .replace("{rules}", rules);
  68. System.out.println(ruleStr);
  69. return FileUtil.getFileFromText(rule_name, ".drl", ruleStr);
  70. }
  71. }

step 4.1 -- 通过字符串创建文件,给上一步用的函数

  1. public static File getFileFromText(String tempFileName, String fileTail, String text) {
  2. try {
  3. File file = File.createTempFile(tempFileName, fileTail);
  4. FileOutputStream fos = new FileOutputStream(file);
  5. fos.write(text.getBytes());
  6. if(fos!=null){
  7. fos.close();
  8. }
  9. return file;
  10. } catch (FileNotFoundException e) {
  11. e.printStackTrace();
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. return null;
  16. }

step 5 -- 规则文件加载,并用以检查当前用户是否满足下发规则条件

  1. BaseRules baseRules = new CarIllegalRules(count, money, points);
  2. if(baseRules!=null) {
  3. logger.info("before fire rules:"+baseRules);
  4. DSLUtil.fireRules(ActivityUtil.createBusinessRuleFile(car_activity, baseRules.getClass(),
  5. baseRules.getParam_text().split(","), baseRules.getParam_value().split(",")), baseRules);
  6. logger.info("after fire rules:"+baseRules);
  7. if(baseRules.isCan_push()) {
  8.         //In here, the rules are used to judge the success of the entity, and you can do something!!!
  9. }
  10. }

小结

本文通过对drools的简单使用步骤的讲解,为大家展示了drools最简单的使用方式,而它能做到的远远不止看到的这些,但是基本框架是这样,大家可以尝试挖掘规则文件的一些黑操作,可以对多变的业务进行极致的抽象,再也不用为了这些重新发版啦,LOL;

PS:想深入了解的同学还是要去看看Rete算法、drools的推理机制等等,本文主要从该引擎的入门出发哈;

最后

大家可以到我的Github上看看有没有其他需要的东西,目前主要是自己做的机器学习项目、Python各种脚本工具、数据分析挖掘项目以及Follow的大佬、Fork的项目等:https://github.com/NemoHoHaloAi

规则引擎 - drools 使用讲解(简单版) - Java的更多相关文章

  1. 开源规则引擎 drools

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

  2. 规则引擎drools封装

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

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

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

  4. JAVA规则引擎 -- Drools

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

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

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

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

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

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

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

  8. Java规则引擎drools:drt动态生成规则并附上具体项目逻辑

    一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...

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

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

随机推荐

  1. python爬取豆瓣首页热门栏目详细流程

    记录一下爬取豆瓣热门专栏的经过,通过这篇文章,你能学会requests,HTMLParser,json的基本使用,以及爬取网页内容的基本思路. 使用模块 1,获取豆瓣首页代码:首先我们需要访问豆瓣页面 ...

  2. 在.net core web 项目中操作MySql数据库(非ORM框架,原生sql语句方式)

    本案例通过MySql.Data和Dapper包执行原生sql,实现对数据库的操作. 操作步骤: 第1步:在MySql数据库中新建表User(使用Navicat For MySql工具) 建表语句: c ...

  3. Mysql高手系列 - 第5天:DML操作汇总,确定你都会?

    这是Mysql系列第5篇. 环境:mysql5.7.25,cmd命令中进行演示. DML(Data Manipulation Language)数据操作语言,以INSERT.UPDATE.DELETE ...

  4. [Error] - Windows卸载程序时,提示错误2503

    1. 打开“任务管理器” 2. 切换到“详细信息”标签页,找到explorer.exe文件,并结束它. 3. 点击“任务管理器”上的文件->运行新任务,输入explorer.ext,勾选“以系统 ...

  5. HDU-3038How Many Answers Are Wrong权值并查集

    How Many Answers Are Wrong 题意:输入一连串的区间和,问和前面的矛盾个数: 思路:我在做专题,知道是并查集,可是还是不知道怎么做,学了一下权值并查集和大佬的优秀思路,感觉回了 ...

  6. codeforce440C-Maximum splitting-规律题

    题意:问一个数最多可以变成几个合数的和: 思路: 时刻提醒自己再看到题目的时候的所作所为,该找规律找规律,想什么ksm,质数判断开根号. 除了1.2.3.5.7.11外,其余的数都可以通过4,6,9获 ...

  7. POJ 3694 Network 无向图双联通+LCA

    一开始题目没看清楚,以为是增加那条边后还有多少桥,所以就当做是无向图tarjan缩点后建树,然后求u,v的最近公共祖先,一直wa. 后来再看题目后才发现边放上去后不会拿下来了,即增加i条边后桥的数量. ...

  8. Codefroces 374 B Inna and Sequence (树状数组 || 线段树)

    Inna and Sequence 题意:先给你一个n,一个m, 然后接下来输入m个数,表示每次拳击会掉出数的位置,然后输入n个数,每次输入1或0在数列的末尾加上1或0,如果输入-1,相应m序列的数的 ...

  9. adb logcat命令

    1.http://blog.csdn.net/tumuzhuanjia/article/details/39555445 2.http://blog.csdn.net/xyz_lmn/article/ ...

  10. [在线+源码]vue全家桶+Typescript开发一款习惯养成APP

    # vue-ts-daily 基于Vue.js的2.5.13版本和TypeScript编写的模仿原生应用的WebApp. [源码地址](https://github.com/xiaomuzhu/vue ...