drools-基础语法
drl是drools rule language的缩写。在规则文件中编写具体的规则内容,一套完整的规则文件的内容构成如下:
- package:包名,package对应的不一定是真正的目录,可以任意写com.xxx,同一个包下的drl文件可以相互访问
- import:用于导入类或者静态方法
- global:全局变量
- function:自定义函数
- query:查询
- rule end:规则体
规则体语法结构
一个规则体通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)
rule "ruleName" //rule关键字,表示规则开始,参数为规则的唯一名称
attributes //规则属性,是rule与when之间的参数,为可选项
when //关键字,后面是规则的条件部分
LHS //是规则的条件部分
then //关键字,后面跟规则的结果部分
RHS //规则的结果或行为
end //关键字,表示一个规则的结束
条件部分
LHS(left hand side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素(自动添加一个eval(true)
)
LHS部分由一个或者多个条件组成,条件又称为pattern,其语法结构为:绑定变量名:Object(Field约束)
。
- 绑定变量名可以省略,通常绑定变量名的命名一般建议以
$
开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的fact对象。 - Field约束部分是需要返回true或者false的0个或多个表达式
- 工作内存中必须存在Object这种类型的Fact对象(类型约束),并且其Field约束中使用到的属性也必须存在(属性约束)
约束连接
在LHS中,可以包含0~n个条件,多个pattern之间可以采用&&
、,
或者不写来代表and,也可以使用||
来代表or。例如:
$Order:(amout>=100 && amout<=500)
比较操作符
在drools中提供了12种类型的比较操作符
操作符 | 说明 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
contains | 检查一个fact对象的某个属性值是否包含一个指定的对象 |
not contains | 检查一个fact对象的某个属性值是否不包含一个指定的对象 |
memberOf | 判断一个fact对象的某个属性是否在一个或多个集合中 |
not memberOf | 判断一个fact对象的某个属性是否不在一个或多个集合中 |
matches | 判断一个fact对象的属性是否与提供的标准的java正则表达式匹配 |
not matches | 判断一个fact对象的属性是否不与提供的标准的java正则表达式匹配 |
结果部分
insert
insert函数的作用和我们在java类中调用StatefullKnowledgeSession对象的insert方法的作用相同,都是用来将一个fact对象插入到当前的working memory当中
注意:
一旦调用insert函数,那么drools会重新与所有的规则再重新匹配一遍,对于没有设置no-loop属性为true的规则,如果条件满足,不管之前是否执行过都会再执行一次,这个特性不仅存在于insert函数上,update、retract也具有该特性,所以在某些情况下因考虑不周调用insert、update或retract容易发生死循环
update
update函数用来实现对当前working memory当中的fact进行更新,用来告诉当前的working memory该fact对象已经发生了变化
retract
retract函数用来将working memory当中的某个fact对象从working memory中删除
属性部分
属性名 | 说明 |
---|---|
salience | 指定规则执行优先级,数字越大优先级越高,默认为0 |
dialect | 指定规则使用的语言类型,取值为java和mvel |
enabled | 指定规则是否启用 |
date-effective | 指定规则生效时间 |
date-expires | 指定规则失效时间 |
activation-group | 激活分组,具有相同分组名称的规则只能有一个触发,可以通过优先级来选择谁执行 |
agenda-group | 议程分组,只有获取焦点的组才有可能触发。通过kieSession.getAgenda().getAgendaGroup("xxx") 或者auto-focus 来设置焦点 |
timer | 定时器,指定规则触发时间。例如timer(5s 2s) 5秒后触发,每两秒执行一次;timer(cron:0/1 * * * * ?) 每隔1秒触发一次 |
auto-focus | 自动获取焦点,一般结合agenda-group一起使用 |
no-loop | 用来控制已经执行过的规则在条件满足的时候是否再次执行,防止死循环 |
drools中的时间格式默认是“dd-MMM-yyyy”,如果要修改的话,可以通过System.setProperty(“drools.dateformat”,“yyyy-MM-dd”)来设置
全局变量
全局变量,一般用作执行规则后的结果数据返回或对具体某个服务调用等。定义完全局变量之后,所有的规则中都可以获取和操作定义的全局变量对象
语法:global 对象类型 对象名
可以在java代码中通过kieSession.setGlobal("对象名",对象)
的方式获取配置文件中的全局变量
query查询
query语法提供了一种查询working memory中符合约束条件的fact对象的简单方法。它仅包含规则文件中LHS部分,不同指定“when”和“then”部分。query有一个可选参数集合,每一个参数都有可选类型。如果没有指定类型,则认为Object类型。引擎会尝试强转为需要的类型
对于KieBase来说,query的名字是全局性的,因此不要向同一RuleBase的不同包添加相同名称的query
使用kieSession.getQueryResults(“query_name”)的方法获得查询的结果,方法返回一个列表,从中可以获取匹配查询到的对象
例如:
//无参数
query "q1"
$order:Order(amout>100)
end
//带参数
query "q2" (String amoutParam)
$order:Order(amout==amoutParam)
end
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.newKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession();
Order o1 = new Order();
o1.setAmout(300);
Order o2 = new Order();
o2.setAmout(50);
kieSession.insert(o1);
kieSession.insert(o2);
QueryResults qr = kieSession.getQueryResults("q1");
for (QueryResultsRow row : qr) {
System.out.println(row.get("$order"));
}
System.out.println("----------------");
QueryResults qr2 = kieSession.getQueryResults("q2", 50);
for (QueryResultsRow row : qr2) {
System.out.println(row.get("$order"));
}
kieSession.dispose();
function函数
在规则中可以通过函数来做一些通用的逻辑,相当于java类中的方法一样
例如:
function String format(String name){
return "hello" + name;
}
函数的参数类型和返回值类型和java一样