本文仅包含Drools
的语法介绍, 不涉及如何使用,规则引擎介绍,算法介绍等方面.
规则文件一般都是.drl
文件, 也可以是xml
文件. 我们默认都是用.drl
文件. 一个规则文件大致会有这样的结构:
package /* 包名, 必须, 逻辑上的管理, 不对应物理位置 */
import /* 导入类或方法, 与java中的import类似 */
global /* 全局变量 */
function /* 定义函数 */
query /* 查询 */
rule /* 规则, 可以由多个; 这是规则文件的主要部分 */
来个具体的规则文件的例子:
package com.test.drools;
function void showName(String name) {
System.out.println("我是" + name);
}
rule "rule1"
when
eval(true)
then
System.out.println("hello drools");
showName("test");
end
package
有以下几点
package
是必须的, 且必须放在规则文件第一行;package
的名字是随意的, 不必对应物理路径;java
中package
的概念不同,这里只是逻辑上的一种区分,同样的package
下定义的function
和query
等可以直接使用。import
跟java
中类似, 可以导入类, 也可以直接导入静态方法
定义全局变量,通常用于返回数据和提供服务; 全局变量与fact不通,引擎不能知道全局变量的改变,必须在插入fact之前,设置global变量
定义函数, 为了提高代码复用, 使用java
语法书写
定义一个规则, 格式大致为:
rule "规则名"
<属性><值>
when
条件 (也叫 Left Hand Side, 简称 LHS)
then
结果 (也叫 Right Hand Side, 简称 RHS)
end
主要包含三部分:
LHS
, 定义当前规则的条件; 如 when Message();
判断当前workingMemory
中是否存在Message
对象RHS
, 即当前规则条件满足后执行的操作,可以直接调用Fact
对象的方法来操作应用,可写java代码属性有这些内容: activation-group
, agenda-group
, auto-focus
, date-effective
, date-expires
, dialect
, duration
, duration-value
, enabled
, lock-on-active
, no-loop
, ruleflow-group
, salience
下面挨个解释:
salience
: 优先级, 属性值是一个数字, 数值越大越先执行, 可以是负数, 默认为0
. 这个可以控制规则的执行顺序date-effective
: 设置规则的生效时间, 当前系统时间>=date-effective
时才会触发执行, 值是一个日期格式的字符串, 推荐用法是手动在java代码中设置当前系统的时间格式, 然后按照格式指定时间. 比如: date-expires "2016-01-31 23:59:59"
date-expires
: 设置规则的过期时间, 跟上面正好相反.enabled
: 表示该规则是否可用, 值为布尔类型, 默认是true
, 设置成false
则该规则就不会被执行了dialect
: 设置语言类型, 值为字符串, 一般有两种语言,mvel
和java
, 默认为java
duration
: 规则定时, 值为长整型, 单位为毫秒, 如 duration 3000
, 表示规则在3秒后执行(另外的线程中执行)no-loop
: 是否允许规则多次执行, 值为布尔类型, 默认是false
, 即当前的规则只要满足条件, 可以无限次执行; 对当前传入workingMemory
中的Fact
对象进行修改或者个数的增减时, 就会触发规则重新匹配执行; 设置属性no-loop true
, 表示当前规则只执行一次, 即使RHS
中更新了当前Fact
对象也不会再次执行该规则了. 不过当其他规则里更新了Fact
对象时, 即使有no-loop true
也会触发, 即no-loop true
仅表示本规的RHS
中有更新时不重复执行.lock-on-active
: 是no-loop
的增强版, 与其他属性配合使用;规则的重复执行不一定是本身触发的, 也可能是其他规则触发的, 当在规则上使用ruleflow-group
属性或agenda-group
属性时, 将lock-on-active
属性值设置为true
,可避免因某些Fact
对象被修改而使已经执行过的规则再次被激活执行.activation-group
: 作用是将规则分组, 值为字符串表示组名,这样在执行的时候,具有相同activation-group
属性的规则中只要有一个会被执行,其它的规则都将不再执行。即在具有相同activation-group
属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行.相同activation-group
属性的规则中哪一个会先执行,则可以用salience
之类的属性来实现agenda-group
: 将规则分成若干个Agenda Group
, 默认情况下, 引擎在调用这些设置了agenda-group
属性的规则时需要显示的指定某个Agenda Group
得到Focus(焦点)
,这样位于该Agenda Group
中的规则才会触发执行,否则将不执行
ruleflow-group
: 使用规则流的时候会用到该属性, 作用是将规则分组,然后在规则流当中通过使用ruleflow-group
属性的值,从而使用对应的规则条件部分(Conditions/LHS)用于匹配条件, 也叫匹配模式(Pattern)
条件可以是单个, 也可以有多个, 下面是一些例子
when
eval(true) // 是一个默认的api, 类似于 while(true)
Person() // 当前的 workingMemory 中存在 Pserson 类型的 Fact 对象
$person:Person() // 同上, $person 是给对象起的名字
$bob:Person(name == "bob") // 字段绑定, 存在 Person 类型且属性 name 值为bob的对象
Person($name:name == "bob") // 与上面类似, 只是把名字放到了 $name 变量里
Person(name == $name) // 与上面类似, 只是把名字放到了 $name 变量里
$tom:Person(name == "tom" || name == "Tom") // 条件组合
then
... // 上面起的变量这里可以直接使用
注意:
$person
, $bob
等代表着符合条件的变量的引用, 在后面的条件部分和RHS
部分中可直接使用Person(age == 18 && (name == "tom" || name == "Tom"))
, 若条件全是&&
关系, 可以使用,
代替, 但两者不能混用.Fact
对象(即输入的数据,类似于java bean)的private属性, 在LHS
中必须用.
引用, 如($person.name == "tom")
, 而RHS
中必须使用 getter
和 setter
方法另外drools
提供了十二种比较操作符, 有:>
, >=
, <
, <=
, ==
, !=
, contains
, not contains
, memberOf
, not memberOf
, matches
, not matches
contains
: 是否包含, 被比较对象可以是一个复杂对象也可以是一个简单的值memberOf
: 是否在某个集合中, 与contains
不同的是他被比较的对象是一个集合, 而contains
被比较的对象是单个值或者对象matches
: 正则表达式匹配RHS, 这部分是普通的java
代码, 记得加;
.
另外drools
提供了几个方法:
insert
: 往当前workingMemory
中插入一个新的Fact
对象, 会触发规则的再次执行,除非使用no-loop限定update
: 更新modify
: 修改, 与update
语法不同, 效果一样, 结果都是更新操作retract
: 删除