规则引擎 - drools 使用讲解(简单版) - Java
drools规则引擎
现状:
- 运维同学(各种同学)通过后台管理界面直接配置相关规则,这里是通过输入框、下拉框等完成输入的,非常简单;
- 规则配置完毕后,前端请求后端,此时服务端根据参数(即规则)生成drl规则文件;
- 用户侧有相关请求到达时,服务端加载规则文件(可能是多个,一般一个广告、活动对应一个规则文件),并通过引擎去检查当前用户各种状态是否满足规则文件;
- 将所有满足的规则文件对应的广告、活动进行下发,同时更新用户数据;
- 完成整个drools相关流程;
关于
drools是一款标准、效率高、速度快的开源规则引擎,基于ReteOO算法,目前主要应用场景在广告、活动下发等领域非常多,比如APP的活动下发,通常都是有很多条件限制的,且各种活动层出不穷,无法代码穷举,而如果每次为了一个活动重新发版上线,显然是不合理的,因此通过drools将活动中变的部分抽象为一个个单独的规则文件,来屏蔽这部分的变化,使得系统不需要从代码层面做出改变,当然了为了更加极致的抽象,通常还需要对规则中的一些可配条件(大于、小于、等于、范围、次数等)也提取到数据库中,这样在现有规则不满足要求时,可以直接通过更改数据库的对应规则表来完善,同样不需要改代码;
我们当时的需求主要就是广告、活动下发规则比较多,广告也是各式各样,因此去调研了drools,对drools也没有过多的挖掘其更多特性,因此还需要大家的指点;
drools简单使用
服务端项目中使用drools的几个基本步骤;
step 1 -- 添加相关依赖到maven pom.xml
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>6.4.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.4.0.Final</version>
</dependency>
step 2 -- 创建实体类加载规则文件
public class CarIllegalRules extends BaseRules{
public static void main(String[] args) {
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession ksession = kContainer.newKieSession("ksession-rules");
CarIllegalRules carIllegalRules = new CarIllegalRules(10,500,10);
ksession.insert(carIllegalRules);
ksession.fireAllRules();
System.out.println(carIllegalRules.isCan_push()+","+carIllegalRules.getContent());
} catch (Exception e) {
e.printStackTrace();
}
}
private int illegal_count;
private int illegal_money;
private int illegal_points;
public CarIllegalRules(int illegal_count, int illegal_money, int illegal_points) {
super();
this.illegal_count = illegal_count;
this.illegal_money = illegal_money;
this.illegal_points = illegal_points;
this.param_value = "illegal_count,illegal_money,illegal_points";
}
@Override
public String toString() {
return "CarIllegalRules [illegal_count=" + illegal_count + ", illegal_money=" + illegal_money
+ ", illegal_points=" + illegal_points + ", can_push=" + can_push + ", content=" + content + ", tts="
+ tts + "]";
}
public int getIllegal_count() {
return illegal_count;
}
public void setIllegal_count(int illegal_count) {
this.illegal_count = illegal_count;
}
public int getIllegal_money() {
return illegal_money;
}
public void setIllegal_money(int illegal_money) {
this.illegal_money = illegal_money;
}
public int getIllegal_points() {
return illegal_points;
}
public void setIllegal_points(int illegal_points) {
this.illegal_points = illegal_points;
}
}
PS:main函数是用来测试这个类的;
step 3 -- 创建DSLUtils类去执行相应规则
public class DSLUtil {
public static void fireRules(File file, Object rules) {
try {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
Resource resource = kieServices.getResources().newFileSystemResource(file);
fire(rules, kieServices, kfs, resource);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void fireRules(String urlStr, Object rules) {
try {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
Resource resource = kieServices.getResources().newFileSystemResource(FileUtil.getFileFromUrl(urlStr));
fire(rules, kieServices, kfs, resource);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void fire(Object commonRules, KieServices kieServices, KieFileSystem kfs, Resource resource)
throws Exception {
resource.setResourceType(ResourceType.DRL);
kfs.write(resource);
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) {
throw new Exception();
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieBase kBase = kieContainer.getKieBase();
KieSession ksession = kBase.newKieSession();
ksession.insert(commonRules);
ksession.fireAllRules();
}
}
step 4 -- 创建一个类去生成规则文件
比如生成 music.drl 的音乐规则文件,这一步是可选的,区别在于规则文件的生成是代码生成,还是人工生成,我们的项目中是运维同学在后台管理界面通过一些图形化输入框输入一些指定参数,而生成规则文件是服务端代码生成的,因此有了这部分,比较实用,一方面可以降低生成规则文件的门槛,任何人都可以做,另一方面也避免了人工出错的可能;
public class ActivityUtil {
/**
* rule template string
*/
private static String template =
"package com.aispeech.dsl\r\n\r\n" +
"import {entity_package_path};\r\n\r\n" +
"import {entity_package_path}.*;\r\n\r\n" +
"rule \"{rule_name}\"\r\n\r\n" +
"when\r\n" +
"\t{instance_name}:{class_name}({rules})\r\n" +
"then\r\n" +
"\t{do}\r\n" +
"end";
private static final String AND = " && ";
private static final String OR = " || ";
/**
* get business rule file xxx.drl
* @param carActivity user info entity
* @param clazz entity class
* @return
*/
public static File createBusinessRuleFile(Car_activity carActivity, Class clazz, String[] param_texts, String[] param_values) {
String ruleStr = template;
String entity_package_path = (clazz+"").substring(6);
String rule_name = "rule_"+carActivity.getId();
String class_name = (clazz+"").substring((clazz+"").lastIndexOf(".")+1);
String instance_name = class_name.toLowerCase();
String rules = "";
JSONArray conditionArray = JSONArray.parseArray(carActivity.getAim_condition());
for(int i=0;i<conditionArray.size();i++) {
JSONObject condition = conditionArray.getJSONObject(i);
rules += "\r\n\t\t("+condition.getString("param")+condition.getString("operator")+condition.getString("value")+")" + AND;
}
rules = rules.length()>0?rules.substring(0, rules.lastIndexOf(AND)):rules;
for (String param_value : param_values) {
rules += "\r\n\t\t,"+param_value.toLowerCase()+":"+param_value;
}
String content = JSONObject.parseObject(carActivity.getContent()).getString("content");
String tts = carActivity.getTts();
for (int i=0;i<param_texts.length;i++) {
content = content.replace("#"+param_texts[i]+"#", "\"+"+param_values[i]+"+\"");
tts = tts.replace("#"+param_texts[i]+"#", "\"+"+param_values[i]+"+\"");
}
String _do = instance_name+".setCan_push(true);";
_do += "\r\n\t" + instance_name+".setContent(\""+content+"\");";
_do += "\r\n\t" + instance_name+".setTts(\""+tts+"\");";
return returnFile(ruleStr, entity_package_path, rule_name, class_name, instance_name, _do, rules);
}
/**
* @param ruleStr
* @param entity_package_path
* @param rule_name
* @param class_name
* @param instance_name
* @param _do
* @param rules
* @return
*/
private static File returnFile(String ruleStr, String entity_package_path, String rule_name, String class_name,
String instance_name, String _do, String rules) {
ruleStr = ruleStr.replace("{entity_package_path}", entity_package_path)
.replace("{rule_name}", rule_name)
.replace("{class_name}", class_name)
.replace("{instance_name}", instance_name)
.replace("{do}", _do)
.replace("{rules}", rules);
System.out.println(ruleStr);
return FileUtil.getFileFromText(rule_name, ".drl", ruleStr);
}
}
step 4.1 -- 通过字符串创建文件,给上一步用的函数
public static File getFileFromText(String tempFileName, String fileTail, String text) {
try {
File file = File.createTempFile(tempFileName, fileTail);
FileOutputStream fos = new FileOutputStream(file);
fos.write(text.getBytes());
if(fos!=null){
fos.close();
}
return file;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
step 5 -- 规则文件加载,并用以检查当前用户是否满足下发规则条件
BaseRules baseRules = new CarIllegalRules(count, money, points);
if(baseRules!=null) {
logger.info("before fire rules:"+baseRules);
DSLUtil.fireRules(ActivityUtil.createBusinessRuleFile(car_activity, baseRules.getClass(),
baseRules.getParam_text().split(","), baseRules.getParam_value().split(",")), baseRules);
logger.info("after fire rules:"+baseRules);
if(baseRules.isCan_push()) {
//In here, the rules are used to judge the success of the entity, and you can do something!!!
}
}
小结
本文通过对drools的简单使用步骤的讲解,为大家展示了drools最简单的使用方式,而它能做到的远远不止看到的这些,但是基本框架是这样,大家可以尝试挖掘规则文件的一些黑操作,可以对多变的业务进行极致的抽象,再也不用为了这些重新发版啦,LOL;
PS:想深入了解的同学还是要去看看Rete算法、drools的推理机制等等,本文主要从该引擎的入门出发哈;
最后
大家可以到我的Github上看看有没有其他需要的东西,目前主要是自己做的机器学习项目、Python各种脚本工具、数据分析挖掘项目以及Follow的大佬、Fork的项目等:https://github.com/NemoHoHaloAi
规则引擎 - drools 使用讲解(简单版) - Java的更多相关文章
- 开源规则引擎 drools
java语言开发的开源业务规则引擎 DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用 ...
- 规则引擎drools封装
一.前言 网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践 ...
- 开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule
直接进入正题 我们在使用开源规则引擎 Drools 的时候, 启动的时候可能会抛出如下异常: Caused by: java.lang.ClassCastException: cn.com.cheng ...
- JAVA规则引擎 -- Drools
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
- [Drools]JAVA规则引擎 -- Drools 2
上一篇文章 http://blog.csdn.net/quzishen/archive/2011/01/25/6163012.aspx 描述了一些常用的drools的语法标签和一个模拟实例即发送积分的 ...
- [Drools]JAVA规则引擎 -- Drools
Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
- 规则引擎drools的简单使用
规则引擎适用于有复杂多变的规则,如商品满减.积分赠送.考勤规则等 一.引入maven依赖 <dependency> <groupId>org.drools</groupI ...
- Java规则引擎drools:drt动态生成规则并附上具体项目逻辑
一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...
- 小明历险记:规则引擎drools教程一
小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...
随机推荐
- python 04 列表
1.列表——list [ ] 有序.可变.支持索引查看. 存储数据,支持大多数数据类型:字符串,数字,布尔值.列表.集合.元组.字典等. 1.1 定义: lst(勿用list) lst = [&qu ...
- Java 并发:学习Thread 类
Java 中 Thread类 的各种操作与线程的生命周期密不可分,了解线程的生命周期有助于对Thread类中的各方法的理解.一般来说,线程从最初的创建到最终的消亡,要经历创建.就绪.运行.阻塞 和 消 ...
- Leetcode之分治法专题-169. 求众数(Majority Element)
Leetcode之分治法专题-169. 求众数(Majority Element) 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是 ...
- (五十二)c#Winform自定义控件-LED数字
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- C#开发BIMFACE系列13 服务端API之获取转换状态
系列目录 [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列12 服务端API之文件转换>中详细介绍了7种文件转换的方法.发起源文件/模型转换后,转换过程可能成功 ...
- Struts2:request & response
整理自网上: 1. 获取Request和Response的方法 1.1. ServletActionContext的静态方法 HttpServletRequest request = ...
- iOS Autoresizing Autolayout Size classes
Autoresizing:出现最早,仅仅能够针对父控件做约束(注意:要关闭Autolayout&Size classes才能够看到Autoresizing) 代码对应: UIView.h中的a ...
- fiddler的安装与使用(二)使用fiddler捕获会话信息
前章回顾: 上一遍文章我们已经安装好了fiddler,并解了fiddler的工作原理,接下来开始使用fiddler捕获浏览器会话信息. fiddler基本界面: 首先启动fiddler,然后打开浏览器 ...
- poj2186Popular Cows+tarjan缩点+建图
传送门: 题意: 给出m条关系,表示n个牛中的崇拜关系,这些关系满足传递性.问被所有牛崇拜的牛有几头: 思路: 先利用tarjan缩点,同一个点中的牛肯定就是等价的了,建立新的图,找出其中出度为0的点 ...
- 洛谷P1939【模板】矩阵加速(数列)+矩阵快速幂
思路: 这个 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1] (x>3) 可以想成: [a(n) ] [1 0 1] [a(n-1) ] [a(n-1) ] = ...