在前面的章节中我们已经实现了一个简单规则引擎的使用。留心的朋友可能已经发现规则引擎的优势所在,那就是将可变的部分剥离出来放置在DRL文件中,规则的变化只用修改DRL文件中的逻辑即可,而其他相关的业务代码则几乎不用改动。
本章节的重点介绍规则文件的构成、语法函数、执行及各种属性等。
一个标准的规则文件的格式为已“.drl”结尾的文本文件,因此可以通过记事本工具进行编辑。规则放置于规则文件当中,一个规则文件可以放置多条规则。在规则文件当中也可以存放用户自定义的函数、数据对象及自定义查询等相关在规则当中可能会用到的一些对象。
从架构角度来讲,一般将同一业务的规则放置在同一规则文件,也可以根据不同类型处理操作放置在不同规则文件当中。不建议将所有的规则放置与一个规则文件当中。分开放置,当规则变动时不至于影响到不相干的业务。读取构建规则的成本业务会相应减少。
标准规则文件的结构如下:
package package-name imports globals functions queries rules
package:在一个规则文件当中package是必须的,而且必须放置在文件的第一行。package 的名字是随意的,不必必须对应物理路径,这里跟java的package的概念不同,只是逻辑上的区分,但建议与文件路径一致。同一的package下定义的function和query等可以直接使用。
比如,上面实例中package的定义:
package com.rules
import:导入规则文件需要的外部变量,使用方法跟java相同。像java的是import一样,还可以导入类中的某一个可访问的静态方法。(特别注意的是,某些教程中提示import引入静态方法是不同于java的一方面,可能是作者没有用过java的静态方法引入。)另外,目前针对Drools7版本,static和function关键字的效果是一样的。
import static com.secbro.drools.utils.DroolsStringUtils.isEmpty; import function com.secbro.drools.utils.DroolsStringUtils.isEmpty;
rules:定义一个条规则。rule “ruleName”。一条规则包含三部分:属性部分、条件部分和结果部分。rule规则以rule开头,以end结尾。
属性部分:定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等。
条件部分,简称LHS,即Left Hand Side。定义当前规则的条件,处于when和then之间。如when Message();判断当前workingMemory中是否存在Message对象。LHS中,可包含0~n个条件,如果没有条件,默认为eval(true),也就是始终返回 true。条件又称之为 pattern(匹配模式),多个pattern之间用可以使用and或or来进行连接,同时还可以使用小括号来确定pattern的优先级。
结果部分,简称RHS,即Right Hand Side,处于then和end之间,用于处理满足条件之后的业务逻辑。可以使用LHS部分定义的变量名、设置的全局变量、或者是直接编写Java 代码。
RHS部分可以直接编写Java代码,但不建议在代码当中有条件判断,如果需要条件判断,那么需要重新考虑将其放在LHS部分,否则就违背了使用规则的初衷。
RHS部分,提供了一些对当前Working Memory实现快速操作的宏函数或对象,比如 insert/insertLogical、update/modify和retract等。利用这些函数可以实现对当前Working Memory中的Fact对象进行新增、修改或删除操作;如果还要使用Drools提供的其它方法,可以使用另一个宏对象drools,通过该对象可以使用更多的方法;同时Drools 还提供了一个名为kcontext的宏对象,可以通过该对象直接访问当前Working Memory的 KnowledgeRuntime。
标准规则的结构示例:
rule "name" attributes when LHS then RHS end
LHS为空示例:
rule "name" when then end