drools规则引擎使用文档
文章目录
一、规则文件结构
package
import
function // Optional
query // Optional
declare // Optional
global // Optional
rule "rule name"
// Attributes
when
// Conditions
then
// Actions
end
rule "rule2 name"
...
-
package:可选,默认值defaultpkg(行尾
;
可以省略)若当前kbase指定路径下所有drl均未指定package,则为defaultpkg;
每个drl文件中仅可出现一次,且必须置于其它代码之前。
注意:package namespace建议与kbase packages目录保持一致,否则在最新版本中无法通过kbase获取package对象。
-
import:可选,自动导入package同名包及java.lang.*下的类;
-
global:可选,一般用于Service服务类的导入,例如
emailService
、smsService
,甚至是Spring 容器上下文对象applicationContext
。 -
依据上图
import
、declare
、global
、function
、query
、rule
位置是可以互换的。 -
注释部分
//
、/*...*/
,可出现在代码的任何地方,会被编译器忽略。示例:
二、规则体结构
rule "rule_name"
// Attribute
// Attribute
when
// Conditions
then
// Actions
end
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvYy4GXW-1630918204682)(https://docs.jboss.org/drools/release/7.54.0.Final/drools-docs/html_single/LanguageReference/rule.png)]
1.Attribute
ruleflow-group
和agenda-group
概念已统一,ruleflow-group
讲覆盖agenda-group
属性。
Since version 6.x the two concepts have been unified, the ruleflow-group name will override the agenda-group.
Attribute
之间可以使用,
分割,而非;
(,
可省略)- 依据上图
salience
、enabled
、date-effective
、date-expires
、no-loop
、agenda-group
、activation-group
、duration
、timer
、calendar
、auto-focus
、lock-on-active
、ruleflow-group
、dialect
、位置是可以互换的。
示例:
package com.example.drools;
dialect "mvel"
rule "rule1"
salience 10
enabled true
date-effective "4-Sep-2018"
date-expires "4-Sep-2022"
no-loop true
agenda-group "agenda-group-1"
activation-group "activation-group-1"
duration 1000
timer (cron:0/10 * * * * ? )
// calendar "* * 0-7,18-23 ? * *"
auto-focus false
lock-on-active false
// 覆盖agenda-group属性值
// ruleflow-group "ruleflow-group-1"
// 覆盖包级别方言
dialect "java"
when
then
System.out.println("rule1");
end
2.Conditions
条件部分由0个或多个patterns组成,多个pattern之间使用
and
、or
、not
组成,默认值and
;pattern括号内部由0个或多个constraints约束部分组成,多个constrain可用
,
分割(,
语法上等同于&&,但优先级小于&&和||);
- from和entry-point
from和entry-point一起使用,实现
eval
时载入数据;
rule "Authorize withdrawal"
when
WithdrawRequest( $ai : accountId, $am : amount ) from entry-point "ATM Stream"
CheckingAccount( accountId == $ai, balance > $am )
then
// Authorize withdrawal.
end
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.EntryPoint;
// Create your KIE base and KIE session as usual:
KieSession session = ...
// Create a reference to the entry point:
EntryPoint atmStream = session.getEntryPoint("ATM Stream");
// Start inserting your facts into the entry point:
atmStream.insert(aWithdrawRequest);
- accumulate
自定义聚合函数导入
import accumulate AverageAccumulateFunction.AverageData average
rule "Average profit"
when
$order : Order()
accumulate( OrderItem( order == $order, $cost : cost, $price : price );
$avgProfit : average( 1 - $cost / $price ) )
then
// Average profit for `$order` is `$avgProfit`.
end
3.Actions
- 数据操作类
actions包括
set
、modify
、update
、insertLogical
、delete
。
- drools内部变量调用,
drools
、kcontext
rule "rule2"
when
then
System.out.println(drools.getRule().getName());
System.out.println(kcontext.getKieRuntime().getEnvironment());
end
三、Query语法

说明:
Query
支持可选参数集合,每一个参数都有可选的类型。如果没有指定类型,则默认为Object类型。,支持Query
间嵌套调用;LHS
和Rule
中的LHS
语法一致代表Pattern
;Query为了更加紧凑的代码风格,增加了对positional syntax
位置语法的支持。
1.基本查询
- 无参
query "people under the age of 21"
$person : Person( age < 21 )
end
- 有参
query contains(String $s, String $c)
$s := String( this.contains( $c ) )
end
说明:
:=
为pattern with unification
; 虽然drools不允许重复声明"绑定",但是支持跨多个属性的参数统一。示例:
declare PersonFact
firstName : String @position( 1 )
lastName : String @position( 0 )
age : int @position( 2 )
id : int @position( 3 )
occupation: String
end
rule "rule2"
when
// 约束1 限定firstName和lastName;约束2 限定age范围;二者使用id统一参数声明内连接
PersonFact("cube", $b:"jack"; $a: age, $id:= id)
PersonFact(age<10, $id:= id)
then
System.out.println($a);
end
2.位置语法
positional syntax
位置语法用于简化LHS
部分代码;可混合使用常规语法
和命名语法
,两者使用;
分割,但是位置语法
必须放于前;以
Location
类型为例:
declare Location
thing : String
location : String
end
- Pattern示例-正确
Location(thing == x, location == y)
Location(x; location == y)
Location(x, y;) // x-代表position为0的字段即thing y-代表position为1的字段即location
Location(x; $p:location == y) // $p-代表patternBinding参数
Location(x; $p:location) // 同上
Location(x, $p;) // 同上
- Pattern示例-错误
Location(thing == x, y;)
Location(thing == x; y;)
四、类型定义与注解
事实类型元数据可描述在类级别和字段级别,语法格式为
@key(value)
,例如@position(0)
1.类型定义
- 无元数据描述信息
import java.util.Date
declare Person
name : String
dateOfBirth : Date
address : Address
end
- 有元数据描述信息
import java.util.Date
declare Person
@author( Bob )
@dateOfCreation( 01-Feb-2009 )
name : String @key @maxLength( 30 )
dateOfBirth : Date
address : Address
end
2.预定义的元数据标签
元数据 | 作用域 | 可选值 | 默认值 | 描述 |
---|---|---|---|---|
@role | class | fact,event | fact | 该标记决定在复杂事件处理期间,给定的事实类型是作为常规事实对象 处理还是作为Drools引擎中的事件对象 处理。 |
@timestamp | class | session clock 或自定义时间戳属性(可为attribute) | session clock | 支持参数:会话时钟时间或自定义时间戳属性 |
@duration | class | 时间间隔或时间点(可为attribute) | Null (zero) | 该标记决定Drools引擎中事件的持续时间 |
@expires | class | [#d][#h][#m][#s][[ms]] | Null (默认时间不在匹配和激活时过期) | 此标记决定事件在Drools引擎的工作内存中过期之前的时间。默认情况下,当事件不再匹配和激活任何当前规则时,该事件将过期。您可以定义事件过期的时间。这个标记定义还覆盖了根据时间约束和KIE基中的滑动窗口计算的隐式过期偏移量。只有当Drools引擎以流模式运行时,此标记才可用。 |
@typesafe | class | true,false | true | 该标记决定给定的事实类型是否使用类型安全进行编译。 |
@serialVersionUID | class | integer | Null | 序列化ID,考虑到兼容性建议在相关类或DRL文件类型声明过程中显式指定serialVersionUID (若未指定则根据类各方面特征自动计算)。 |
@key | attribute | - | - | 参与计算equals() 和hashCode() 的属性;同时Drools引擎会隐式地定义3个构造函数,分别为无参构造器、全参构造器、附带@key属性的构造器。 |
@position | attribute | integer | None | 优先级原则:子类>父类;显式指定>未指定;声明顺序 |
@classReactive | class | - | - | 全局开关处于开启状态(默认 ALWAYS),代表属性响应性 生效;可以通过该标记禁用指定类的属性响应性 ,实现微调;与ALLOWED 对应,每次触发规则时重新评估事实的所有事实模式。 |
@propertyReactive | class | - | - | 全局开关处于可选状态(ALLOWED)时,代表属性响应性 停用;可以通过该标记启用指定类的属性响应性 ,实现微调;与ALWAYS 对应,仅对给定模式内受约束或绑定的修改属性做出反应。DISABLED 状态时,所有属性更改侦听器都将被忽略(即不重新评估)。 |
@watch | factPattern | Property name, * (all), ! (not), !* (no properties) | None | 全局开关处于开启状态(ALWAYS)或处于可选状态(ALLOWED)且类被标记为@propertyReactive 时,总之,当前类型处于属性响应性 状态时,你可以使用通配符或非操作过滤属性;处于非属性响应性 ,使用@watch 或出现冲突例如@watch( firstName, ! firstName ) )时编译错误。 |
@propertyChangeSupport | class | - | - | 增加该标记,可使drools可以监听javabean的属性变动。 |
下面以典型的电信领域语音呼叫为例
public class VoiceCall {
private String originNumber;
private String destinationNumber;
private Date callDateTime;
private long callDuration; // in milliseconds
// Constructors, getters, and setters
}
- 类级别元数据
declare VoiceCall
@role( event )
@timestamp( callDateTime )
@duration( callDuration )
@expires( 1h35m )
@typesafe( false )
@serialVersionUID( 42 )
end
- @key
declare Person
firstName : String @key
lastName : String @key
age : int
end
- @position
declare Person
firstName : String @position( 1 )
lastName : String @position( 0 )
age : int @position( 2 )
occupation: String
end
declare Student extends Person
degree : String @position( 1 )
school : String @position( 0 )
graduationDate : Date
end
- @watch
// Listens for changes in both `firstName` (inferred) and `lastName`:
Person(firstName == $expectedFirstName) @watch( lastName )
// Listens for changes in all properties of the `Person` fact:
Person(firstName == $expectedFirstName) @watch( * )
// Listens for changes in `lastName` and explicitly excludes changes in `firstName`:
Person(firstName == $expectedFirstName) @watch( lastName, !firstName )
// Listens for changes in all properties of the `Person` fact except `age`:
Person(firstName == $expectedFirstName) @watch( *, !age )
// Excludes changes in all properties of the `Person` fact (equivalent to using `@classReactivity` tag):
Person(firstName == $expectedFirstName) @watch( !* )
- @propertyChangeSupport
declare Person
@propertyChangeSupport
end
3.java中使用声明的FactType
import java.util.Date;
import org.kie.api.definition.type.FactType;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
...
// Get a reference to a KIE base with the declared type:
KieBase kbase = ...
// Get the declared fact type:
FactType personType = kbase.getFactType("org.drools.examples", "Person");
// Create instances:
Object bob = personType.newInstance();
// Set attribute values:
personType.set(bob, "name", "Bob" );
personType.set(bob, "dateOfBirth", new Date());
personType.set(bob, "address", new Address("King's Road","London","404"));
// Insert the fact into a KIE session:
KieSession ksession = ...
ksession.insert(bob);
ksession.fireAllRules();
// Read attributes:
String name = (String) personType.get(bob, "name");
Date date = (Date) personType.get(bob, "dateOfBirth");
Tips:
a.实际使用过程中,可使用Map简化操作
org.kie.api.definition.type.FactType#setFromMap
org.kie.api.definition.type.FactType#getAsMap
b.尽管API的行为类似于Java反射,但API并不使用反射,而是依赖于使用生成的字节码实现的性能更好的访问器。
参考:
未完待续……