例子源自互联网
1、例子
环境搭建可以参照:Drools(JbossRules)笔记(1)-- Drools入门学习
我们假定如下情景:网站伴随业务产生而进行的积分发放操作。比如支付宝信用卡还款奖励积分等。
我们定义一下发放规则:
积分的发放参考因素有:交易笔数、交易金额数目、信用卡还款次数、生日特别优惠等。
定义规则:
过生日,则加10分,并且将当月交易比数翻倍后再计算积分
2011-01-08 - 2011-08-08每月信用卡还款3次以上,每满3笔赠送30分
当月购物总金额100以上,每100元赠送10分
当月购物次数5次以上,每五次赠送50分
特别的,如果全部满足了要求,则额外奖励100分
发生退货,扣减10分
退货金额大于100,扣减100分
代码思路规划,一共6个文件:两个drl规则文件,一个用于添加积分,一个用于扣减积分;一个积分计算对象(PointDomain Fact);一个RuleBaseFacatory工厂类;一个积分规则接口,一个积分规则接口实现类(包括测试方法)。
1.1、规则文件
addpoint.drl
package com.esom.tech.drools.pointrule.addpoint.drl import com.esom.tech.drools.pointrule.PointDomain; // 过生日,则加10分,并且将当月交易比数翻倍后再计算积分 rule birthdayPoint salience 100 when $pointDomain : PointDomain(birthDay == true) then $pointDomain.setPoint($pointDomain.getPoint()+10); $pointDomain.setBuyNums($pointDomain.getBuyNums()*2); $pointDomain.setBuyMoney($pointDomain.getBuyMoney()*2); $pointDomain.setBillThisMonth($pointDomain.getBillThisMonth()*2); $pointDomain.recordPointLog($pointDomain.getUserName(),"birthdayPoint"); end // 2013-01-08 - 2013-08-08每月信用卡还款3次以上,每满3笔赠送30分 rule billThisMonthPoint salience 99 date-effective "2013-01-08 23:59:59" date-expires "2013-08-08 23:59:59" when $pointDomain : PointDomain(billThisMonth >= 3) then $pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBillThisMonth()/3*30); $pointDomain.recordPointLog($pointDomain.getUserName(),"billThisMonthPoint"); end // 当月购物总金额100以上,每100元赠送10分 rule buyMoneyPoint salience 98 when $pointDomain : PointDomain(buyMoney >= 100) then $pointDomain.setPoint($pointDomain.getPoint()+ (int)$pointDomain.getBuyMoney()/100 * 10); $pointDomain.recordPointLog($pointDomain.getUserName(),"buyMoneyPoint"); end // 当月购物次数5次以上,每五次赠送50分 rule buyNumsPoint salience 97 when $pointDomain : PointDomain(buyNums >= 5) then $pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBuyNums()/5 * 50); $pointDomain.recordPointLog($pointDomain.getUserName(),"buyNumsPoint"); end // 特别的,如果全部满足了要求,则额外奖励100分 rule allFitPoint salience 96 when $pointDomain:PointDomain(buyNums >= 5 && billThisMonth >= 3 && buyMoney >= 100) then $pointDomain.setPoint($pointDomain.getPoint()+ 100); $pointDomain.recordPointLog($pointDomain.getUserName(),"allFitPoint"); end
subpoint.drl
package com.esom.tech.drools.pointrule.subpoint.drl import com.esom.tech.drools.pointrule.PointDomain; // 发生退货,扣减10分 rule subBackNumsPoint salience 10 when $pointDomain : PointDomain(backNums >= 1) then $pointDomain.setPoint($pointDomain.getPoint()-10); $pointDomain.recordPointLog($pointDomain.getUserName(),"subBackNumsPoint"); end // 退货金额大于100,扣减100分 rule subBackMondyPoint salience 9 when $pointDomain : PointDomain(backMondy >= 100) then $pointDomain.setPoint($pointDomain.getPoint()-10); $pointDomain.recordPointLog($pointDomain.getUserName(),"subBackMondyPoint"); end
1.2、积分计算对象
PointDomain.java
package com.esom.tech.drools.pointrule; public class PointDomain { // 用户名 private String userName; // 是否当日生日 private boolean birthDay; // 增加积分数目 private long point; // 当月购物次数 private int buyNums; // 当月退货次数 private int backNums; // 当月购物总金额 private double buyMoney; // 当月退货总金额 private double backMondy; // 当月信用卡还款次数 private int billThisMonth; /** * 记录积分发送流水,防止重复发放 * @param userName 用户名 * @param type 积分发放类型 */ public void recordPointLog(String userName, String type){ System.out.println("增加对"+userName+"的类型为"+type+"的积分操作记录."); } //get、set方法... }
1.3、RuleBaseFacatory工厂类
RuleBaseFacatory.java
package com.esom.tech.drools.pointrule; import org.drools.RuleBase; import org.drools.RuleBaseFactory; import com.esom.tech.pattern.Singleton; public class RuleBaseFacatory { private static RuleBase ruleBase; public static RuleBase getRuleBase() { if (ruleBase == null) { synchronized (Singleton.class) { if (ruleBase == null) { ruleBase = RuleBaseFactory.newRuleBase(); } } } return ruleBase; } }
1.4、积分规则接口及实现
PointRuleEngine.java
package com.esom.tech.drools.pointrule; public interface PointRuleEngine { //初始化规则引擎 public void initEngine(); //刷新规则引擎中的规则 public void refreshEnginRule(); /** * 执行规则引擎 * @param pointDomain 积分Fact */ public void executeRuleEngine(final PointDomain pointDomain); }
PointRuleEngineImpl.java
package com.esom.tech.drools.pointrule; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.ArrayList; import java.util.List; import org.drools.RuleBase; import org.drools.StatefulSession; import org.drools.compiler.PackageBuilder; import org.drools.spi.Activation; public class PointRuleEngineImpl implements PointRuleEngine { private RuleBase ruleBase; //初始化规则引擎:规则收集 public void initEngine() { // 设置时间格式 System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss"); ruleBase = RuleBaseFacatory.getRuleBase(); try { PackageBuilder backageBuilder = getPackageBuilderFromDrlFile(); ruleBase.addPackages(backageBuilder.getPackages()); } catch (Exception e) { e.printStackTrace(); } } //刷新规则引擎中的规则 public void refreshEnginRule() { ruleBase = RuleBaseFacatory.getRuleBase(); org.drools.rule.Package[] packages = ruleBase.getPackages(); for (org.drools.rule.Package pg : packages) { ruleBase.removePackage(pg.getName()); } initEngine(); } //执行规则引擎:规则执行 public void executeRuleEngine(final PointDomain pointDomain) { if (null == ruleBase.getPackages()|| 0 == ruleBase.getPackages().length) { return; } StatefulSession statefulSession = ruleBase.newStatefulSession(); statefulSession.insert(pointDomain); // fire statefulSession.fireAllRules( //Agenda 负有规划激活规则运行的责任 //Agenda Filter,过滤名字含test的规则 new org.drools.spi.AgendaFilter() { public boolean accept(Activation activation) { return !activation.getRule().getName().contains("test"); } } ); statefulSession.dispose(); } //从Drl规则文件中读取规则:规则编译 private PackageBuilder getPackageBuilderFromDrlFile() throws Exception { // 获取测试脚本文件 List<String> drlFilePath = getTestDrlFile(); // 装载测试脚本文件 List<Reader> readers = readRuleFromDrlFile(drlFilePath); PackageBuilder backageBuilder = new PackageBuilder(); for (Reader r : readers) { backageBuilder.addPackageFromDrl(r); } // 检查脚本是否有问题 if (backageBuilder.hasErrors()) { throw new Exception(backageBuilder.getErrors().toString()); } return backageBuilder; } //装载规则文件 private List<Reader> readRuleFromDrlFile(List<String> drlFilePath)throws FileNotFoundException { if (null == drlFilePath || 0 == drlFilePath.size()) { return null; } List<Reader> readers = new ArrayList<Reader>(); for (String ruleFilePath : drlFilePath) { readers.add(new FileReader(new File(ruleFilePath))); } return readers; } //获取规则文件 private List<String> getTestDrlFile() { List<String> drlFilePath = new ArrayList<String>(); drlFilePath.add("D:\\workspace\\helloworld\\src\\main\\java\\com\\esom\\tech\\drools\\pointrule\\addpoint.drl"); drlFilePath.add("D:\\workspace\\helloworld\\src\\main\\java\\com\\esom\\tech\\drools\\pointrule\\subpoint.drl"); return drlFilePath; } public static void main(String[] args) throws Exception { PointRuleEngine pointRuleEngine = new PointRuleEngineImpl(); while(true){ System.out.println("请输入命令:"); InputStream is = System.in; BufferedReader br = new BufferedReader(new InputStreamReader(is)); String input = br.readLine(); if(null != input && "s".equals(input)){ System.out.println("初始化规则引擎..."); pointRuleEngine.initEngine(); System.out.println("初始化规则引擎结束."); }else if("e".equals(input)){ final PointDomain pointDomain = new PointDomain(); System.out.println("初始化规则引擎..."); pointRuleEngine.initEngine(); System.out.println("初始化规则引擎结束."); pointDomain.setUserName("hello kity"); pointDomain.setBackMondy(100d); pointDomain.setBuyMoney(500d); pointDomain.setBackNums(1); pointDomain.setBuyNums(5); pointDomain.setBillThisMonth(5); pointDomain.setBirthDay(true); pointDomain.setPoint(0l); pointRuleEngine.executeRuleEngine(pointDomain); System.out.println("执行完毕BillThisMonth:"+pointDomain.getBillThisMonth()); System.out.println("执行完毕BuyMoney:"+pointDomain.getBuyMoney()); System.out.println("执行完毕BuyNums:"+pointDomain.getBuyNums()); System.out.println("执行完毕规则引擎决定发送积分:"+pointDomain.getPoint()); } else if("r".equals(input)){ System.out.println("刷新规则文件..."); pointRuleEngine.refreshEnginRule(); System.out.println("刷新规则文件结束."); } } } }
执行main方法,输入'e',输出:
请输入命令:
e
初始化规则引擎...
初始化规则引擎结束.
增加对hello kity的类型为birthdayPoint的积分操作记录.
增加对hello kity的类型为billThisMonthPoint的积分操作记录.
增加对hello kity的类型为buyMoneyPoint的积分操作记录.
增加对hello kity的类型为buyNumsPoint的积分操作记录.
增加对hello kity的类型为allFitPoint的积分操作记录.
增加对hello kity的类型为subBackNumsPoint的积分操作记录.
增加对hello kity的类型为subBackMondyPoint的积分操作记录.
执行完毕BillThisMonth:10
执行完毕BuyMoney:1000.0
执行完毕BuyNums:10
执行完毕规则引擎决定发送积分:380
请输入命令:
2、 Droolsv API解释
Drools API可以分为三类:规则编译、规则收集和规则的执行
1)PackageBuilder规则编译:规则文件进行编译, 最终产生一批编译好的规则包(Package)供其它的应用程序使用。
2)RuleBase:提供的用来收集应用当中规则(rule)定义的规则库对象,在一个RuleBase当中可以包含普通的规则(rule)、规则流(rule flow)、函数定义(function)、用户自定义对象(type model)等。
3)StatefulSession:是一种最常用的与规则引擎进行交互的方式,它可以与规则引擎建立一个持续的交互通道,在推理计算的过程当中可能会多次触发同一数据集。在用户的代码当中,最后使用完StatefulSession对象之后,一定要调用其dispose()方法以释放相关内存资源。有状态的。
4)StatelessSession:使用StatelessSession对象时不需要再调用dispose()方法释放内存资源不能进行重复插入fact 的操作、也不能重复的调用fireAllRules()方法来执行所有的规则,对应这些要完成的工作在StatelessSession当中只有execute(…)方法,通过这个方法可以实现插入所有的fact 并且可以同时执行所有的规则或规则流,事实上也就是在执行execute(…)方法的时候就在StatelessSession内部执行了insert()方法、fireAllRules()方法和dispose()方法。
StatefulSession和StatelessSession都继承了WorkingMemory。
5) Fact :是指在Drools 规则应用当中,将一个普通的JavaBean插入到规则的WorkingMemory当中后的对象规则可以对Fact 对象进行任意的读写操作,当一个JavaBean 插入到WorkingMemory 当中变成Fact 之后,Fact 对象不是对原来的JavaBean 对象进行Clone,而是原来JavaBean 对象的引用。
3、Drools规则
规则文件格式:
package package-name //包名是必须的,并必须放在第一行。除外其他的位置没要求。
imports
globals
functions
queries
rules
3.1、规则语言
rule "name" //规则名称
attributes //属性部分
when
LHS //left hand sid条件部分
then
RHS //right hand sid结果部分
end
3.1.1、条件部分
条件部分又被称之为Left Hand Side,简称为LHS,条件又称之为pattern(匹配模式):在一个规则当中when与then 中间的部分就是LHS 部分。在LHS 当中,可以包含0~n 个条件,如果LHS 部分为空的话,那么引擎会自动添加一个eval(true)的条件,由于该条件总是返回true,所以LHS 为空的规则总是返回true,在Drools
当中在pattern 中没有连接符号,那么就用and 来作为默认连接,所以在该规则的LHS 部分中两个pattern 只有都满足了才会返回true。默认情况下,每行可以用“;”来作为结束符(和Java 的结束一样),当然行尾也可以不加“;”结尾。
约束连接:对于对象内部的多个约束的连接,可以采用“&&”(and)、“||”(or)和“,”(and)来实现,表面上看“,”与“&&”具有相同的含义,但是有一点需要注意,“,”与“&&”和“||”不能混合使用,也就是说在有“&&”或“||”出现的LHS 当中,是不可以有“,”连接符出现的,反之亦然。
条件操作符:共计12种:>、>=、<、<=、= =、!=、contains、not contains、memberof、not memberof、matches、not matches
1) contains:用来检查一个Fact 对象的某个字段(该字段要是一个Collection或是一个Array 类型的对象)是否包含一个指定的对象。
contains 只能用于对象的某个Collection/Array 类型的字段与另外一个值进行比较,作为比较的值可以是一个静态的值,也可以是一个变量(绑定变量或者是一个global 对象)
package test rule "rule1" when $order:Order(); $customer:Customer(age >20, orders contains $order); then System.out.println($customer.getName()); end
2)not contains:与contains作用相反
3)member of:是用来判断某个Fact 对象的某个字段是否在一个集合(Collection/Array)当中,用法与contains 有些类似,但也有不同,member of 前边是某个数据对象且一定要是一个变量(绑定变量或者是一个global 对象),后边是数据对象集合
package test global String[] orderNames; rule "rule1" when $order:Order(name memberOf orderNames); then System.out.println($order.getName()); end
4)not member of:与member of作用相反
5)matches: 用来对某个Fact 的字段与标准的Java 正则表达式进行相似匹配,被比较的字符串可以是一个标准的Java 正则表达式,但有一点需要注意,那就是正则表达式字符串当中不用考虑“\”的转义问题
package test import java.util.List; rule "rule1" when $customer:Customer(name matches "李.*"); then System.out.println($customer.getName()); end
相关推荐
### Drools JBoss Rules 5 开发者指南 #### 知识点一:Drools 平台介绍 - **定义与背景**:Drools 是一个开源业务规则管理系统(Business Rule Management System, BRMS),它支持开发人员通过声明式编程来实现...
Drools JBoss Rules是JBoss企业中间件产品套件的一部分,它是一个基于Java平台的业务规则引擎...通过这样的学习方式,开发者可以更好地利用Drools JBoss Rules来解决实际的业务问题,提高工作效率和软件质量。
jboss 规则引擎 drools库。 api,core,compiler,jsr94 drools-compiler-5.1.1.jar
《Drools JBoss Rules 5.0 Developer's Guide》是一本全面介绍Drools 5.0的书籍,不仅适合新手入门学习,也适合有一定经验的开发者深入研究。通过本书的学习,读者可以掌握Drools的基本原理和使用技巧,为构建复杂的...
myeclipse安装drools jboss rules规则引擎
drools-persistence-jpa-5.2.0.Final.jar drools
### Drools JBoss Rules 5.0 Developer's Guide:规则引擎技术详解 #### 一、概述 《Drools JBoss Rules 5.0 Developer's Guide》是一本深入讲解Drools规则引擎技术的书籍。本书由Michal Bali编写,旨在帮助读者...
dools是一款开源规则引擎,drools-workbench是它的工作台web程序,可以编译,打包,发布规则,kie-server是可以运行规则的服务器程序, 两个服务单独部署,用户可以通过通过http请求发送数据,然后返回规则额匹配...
快速流口水介绍fast-drools-spring-boot-starter将Drools与Springboot集成在一起,为规则配置和管理提供了更有效,更复杂的模型。 它能够动态更新有关热部署的规则。联系请随时与以下联系人询问我任何问题。 Drools...
drools-workbench-mirror-2
<artifactId>drools-core <version>7.x.y</version> <!-- 替换为实际版本 --> <groupId>org.drools <artifactId>drools-compiler <version>7.x.y</version> <!-- 替换为实际版本 --> ``` 在环境准备好...
提供的文档如《Drools4.0官方使用手册中文.doc》和《Drools5规则引擎开发教程.pdf》是深入学习Drools的重要资料,它们会详细讲解Drools的安装、配置、规则编写、工作流程以及实际应用案例。 总之,Drools 提供了一...
【标题】"drools-wb-guided-template-editor-api-6.1.0.Beta3.zip" 是一个与 Drools 工作台相关的压缩包,它包含的是 Drools 指导模板编辑器 API 的 6.1.0 Beta3 版本。Drools 是一个强大的规则引擎,用于在 Java ...
标题中的"spring-camel-drools-decision-table-example-6.1.0.CR1.zip"表明这是一个关于Spring、Apache Camel和Drools决策表的开源项目示例,使用的版本是6.1.0的候选发布版1(CR1)。这个项目可能展示了如何在...
drools-persistence-jpa-5.2.0.Final-sources.jar jbpm5 源码
maven-drools-plugin-0.3.1-sources.jar
规则引擎 Drools-JBoss Rules 规则引擎是人工智能(Artificial Intelligence)领域中的一种技术,用于实现专家系统,专家系统使用知识表示把知识编码简化成一个可用于推理的知识库。规则引擎是一个基于规则的方法...