一、Drools是什么
概述:
- Drools是一款基于Java语言开发的开源规则引擎技术,可以将复制且多变的业务逻辑从硬编码中脱离出来,以规则脚本的形式存放在文件或者数据库中。从而使得不需要重启服务器就可以生效,达到动态业务。
KIE:
- 在学习drools之前我们需要了解KIE,KIE(Knowledge Is Everything)即
知识就是一切
的缩写,是Jboss一系列项目的总称。而drools就是其中的一个组件,当然KIE还包括OptaPlanner、UberFire、jBPM等。
KIE结构图
OPtaPlanner: 一个本地搜索和优化工具
Drools: 规则引擎,从图中可以看到Drools还指向了Drools-WB,而Drools-WB又指向了KIE-WB。KIE-WB是一个整合了所有且又强大的web IDE。
UberFire: 是一个全新的组件,功能类似Eclipse。
jBPM: 业务流管理组件,用于实现自动化业务流程和决策的工具包。
适用场景:
按行业分类:
- 金融行业 – 黑白名单、风险投保等
- 医疗行业 – 配药用药等
- 电商行业 – 促销平台等
按系统分类:
- 风控系统
- 反欺诈项目
- 决策平台系统
编写HelloWorld:
导入依赖:
<dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.10.0.Final</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies>
在resource目录下创建META-INF包及xml文件:
在resource目录下创建以.drl结尾的规则文件:
package com.dr.drools rule "Hello" when eval(1==1) then System.out.println("Hello drools"); end
编写测试类:
public class HelloWorldTest { @Test public void helloTest(){ KieServices kieServices = KieServices.Factory.get(); KieContainer kieContainer = kieServices.getKieClasspathContainer(); KieSession kieSession = kieContainer.newKieSession("hellodrools"); int count = kieSession.fireAllRules(); System.out.println("执行了" + count + "条规则"); //关闭会话 kieSession.dispose(); } }
规则文件内容结构:
规则文件一般分为三大部分:包路径、规则体、引用
包路径(package):
- 规则文件存放的路径
规则体(rule…):
- 以rule开始end结尾,并且还要为规则指定名称且不能重名,类似数据库中的case when then end。
- rule ~ then 之间可以编写一下属性
- when ~ then 之间编写条件
- then ~ end 之间编写处理结果,但最好不要有逻辑判断
引用(improt):
可以引入函数、对象等
import com.dr.pojo.User import function com.dr.pojo.User.add // 需为静态
如果你想在规则中使用自定义的对象,那就需要插入fack对象中
User user = new User(); user.setUsername("姓名"); user.setAge(18); User.add(19); kieSession.insert(user);
Fack对象:
- 在规则引擎中传输的数据称之为Fack对象,Fack对象可以是javabean也可以是任何一个Object对象。我们编写的规则就需要和fack对象进行匹配。同时drools中还提供了一个内置对fack对象进行数据处理的函数。
- insert/insert-Logical(新增)
- update/modify(修改)
- delete/retract(删除)等
- 在规则引擎中传输的数据称之为Fack对象,Fack对象可以是javabean也可以是任何一个Object对象。我们编写的规则就需要和fack对象进行匹配。同时drools中还提供了一个内置对fack对象进行数据处理的函数。
二、Drools的基础语法:
规则文件:
标准的规则文件都是以
.drl
结尾,当然还可以是.drls
.xml
.xls
.xlsx
。在一个规则文件中可以存放多个规则体,自定义函数,数据对象,自定义查询等。关键字 描述 package 包名,仅限于逻辑上的管理,如果自定义的函数和对象位于同一包下都可以调用 import 导入对象、函数等 global 全局变量 function 自定义函数 queries 自定义查询 rule end 规则体 规则体语法结构:
关键字 描述 rule 规则的开始,并指定唯一规则名称 attributes 规则属性,位于rule和when之间,可选 when 条件,为空默认为true then 满足条件的结果 end 规则的结束
匹配模式(Pattern)
- 匹配模式是指when~then这一条件区域中多个条件进行匹配,可以使用
and
or
&
|
&&
||
,
,其中逗号和跟and
是一个意思。如果你想要取出匹配成功的结果来作为下一个匹配条件的变量那么可以这样做:$变量名: Object(条件)
当然你也可以在(条件)
中 使用。如果你想要在匹配时有优先级,那么()
是最好的选择。
运算符:
因为
Drools
是完全基于Java
语言开发的,所有Java
的的运算符基本都会支持。一般的运算符都有:
+
-
*
/
%
>
>=
<
<=
==
!=
!. 等于 != null
在进行运算时最好用括号包裹起来,这样更不容易出错,因为官方给的案例就这样的而且我在工作中也测试过,如果不用括号包裹起来很有可能不会生效,当然也不会报错。这里需要注意:如果你使用的版本是Drools 6.4那么
,
不能和&&
||
混合使用的,然而其它版本是可以的
约束连接:
contains
和not contains
- contains 用来检查fact对象中的某个属性值释放包含指定的对象值。
- 语法结构:
Object(field[collection] contains | not contains value)
memberOf
和not memberOf
- memberOf 用来判断某个Fact对象的字段值在一个或多个集合/数组中,如果你传入的是一个常量那么drools会将其转为数组,在对Map进行判断时,Drools是对Map的Key进行判断的,如果key都没有那么value自然毫无意义。
- 语法结构:
Object(field memberOf | not memberOf value[collection])
matches
和not matches
- matches 可以用来匹配Fact对象的字段于标准的
Java
正则表达式进行匹配,需要注意的是Java
中的转义字符必须考虑(尽管也可以正常使用),在匹配时最好使用括号包裹起来,这样会更好的避免错误。 - 语法结构:
Object(field matches | not matches "正则表达式")
- matches 可以用来匹配Fact对象的字段于标准的
soundslike
- soundslike 可以用来判断字段值是否和给定的值相同,虽然看上去有点模糊匹配的意思,但我得到的测试结果显示必须要相等才可以。
- 语法结构:
Object(field soundslike value)
str
str不仅可以判断字符串类型的开头和结尾,还可以判断字符串的长度。
语法结构:
Object(field str[startsWith | endsWit | length] value)
好吧,尝试了几次发现在中括号中添加三个属性都会报错,貌似有问题,也有可能是我没弄明白吧
in
和notin
- in 可以用来判断字段值是否在一定的范围内,而这个范围必须用括号包裹起来
- 语法结构:
Object(field in | notin (value))
嵌套约束
在某些情况下需要访问嵌套对象的多个属性,我们可以这样做
Person( name == "mark", address.city == "london", address.country == "uk" )
Person( name == "mark", address.( city == "london", country == "uk") )
&&
和,
- 尽管
&&
和,
都有和的意思但是他们之间也是有优先级的,&&
的优先级高于,
,同时在复合运算时不能混合使用&&
和,
// 不要这样使用 Person( ( age > 50, weight > 80 ) || height > 2 ) // 最好这样使用 Person( ( age > 50 && weight > 80 ) || height > 2 )
- 尽管
获取集合中元素:
LHS: 条件部分,即when ~ then
RHS: 结果部分,即then ~ end
List
- LHS中:
$u: User(usernameList[1] == "张三")
- RHS中:
$u.getUsernameList().get(1);
- LHS中:
Set
- LHS中:
$u: User(usernameSet.iterator.next == "张三")
- RHS中:
$u.getUsernameSet().iterator.next();
- LHS中:
Map
- LHS中:
$u: User(usernameMap.get(key) == "张三")
- RHS中:
$u.getUsernameMap().get(key);
- LHS中:
注释:
- 单行注释:
//
- 多行注释:
/* */
下篇将从Drools规则的属性开始