Drools学习 第二季 基础用法
Drools基础用法:
1.package:对一个规则文件而言,package必须定义,且放在规则文件的第一行。特别的是package名称是随意的,不必必须对应物理路径,跟java中的package不同,这里只是逻辑上的区分 ,同样的package下定义的function和query等可以直接使用;
2.import:导入规则文件需要使用到的外部变量,这里的使用方法跟java相同,但是不同于java的是,这里import导入的不仅仅可以是一个类,也可以是这个类的某一个可访问的静态方法。
3.rule:定义一个规则。rule "ruleName"。定义一个规则可以包含三个部分:
规则以rule关键字开始 ,以end结束;
name紧跟在rule后面,建议使用双引号包含住name;
when相当于java中的if,但是这里的理解为“发生事件/事实存在”,当什么事件发生/事实存在时触发什么(then);
一个事实其实就是一个POJO,所有事实(Fact)都将存放在working Memory中;
属性部分:定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等。
属性部分中: no-loop: 定义当前的规则是否不允许多次循环执行,默认是false,也就是当前的规则只要满足条件,可以无限次执行。什么情况下会出现一条规则执行过一次又被多次重复执行呢?drools提供了一些api,可以对当前传入workingMemory中的Fact对象进行修改或者个数的增减,比如上述的update方法,就是将当前的workingMemory中的Message类型的Fact对象进行属性更新,这种操作会触发规则的重新匹配执行,可以理解为Fact对象更新了,所以规则需要重新匹配一遍,那么疑问是之前规则执行过并且修改过的那些Fact对象的属性的数据会不会被重置?结果是不会,已经修改过了就不会被重置,update之后,之前的修改都会生效。当然对Fact对象数据的修改并不是一定需要调用update才可以生效,简单的使用set方法设置就可以完成,这里类似于java的引用调用,所以何时使用update是一个需要仔细考虑的问题,一旦不慎,极有可能会造成规则的死循环。上述的no-loop true,即设置当前的规则,只执行一次,如果本身的RHS部分有update等触发规则重新执行的操作,也不要再次执行当前规则。 但是其他的规则会被重新执行,岂不是也会有可能造成多次重复执行,数据紊乱甚至死循环?答案是使用其他的标签限制,也是可以控制的:lock-on-active true
lock-on-activetrue:通过这个标签,可以控制当前的规则只会被执行一次,因为一个规则的重复执行不一定是本身触发的,也可能是其他规则触发的,所以这个是no-loop的加强版。当然该标签正规的用法会有其他的标签的配合,后续提及。
date-expires:设置规则的过期时间,默认的时间格式:“日-月-年”,中英文格式相同,但是写法要用各自对应的语言,比如中文:"29-七月-2010",但是还是推荐使用更为精确和习惯的格式,这需要手动在java代码中设置当前系统的时间格式,后续提及。属性用法举例:date-expires "2011-01-31 23:59:59" // 这里我们使用了更为习惯的时间格式
date-effective:设置规则的生效时间,时间格式同上。
duration:规则定时,duration 3000 3秒后执行规则
salience:优先级,数值越大越先执行,这个可以控制规则的执行顺序。
条件部分:即LHS,定义当前规则的条件,如when message();判断当前workingMemory中是否存在Message对象;
结果部分:即RHS,这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用。
例:x:Person(age==25,myname:name)
解析:
其中x代表将Person对象赋值给x,而myname则表示将Person中name字段的值赋给myname变量,供下面操作使用。
Drools提供了十二中类型比较操作符: > >= < <= == != contains/ not contains / memberOf / not memberOf /matches/ not matches not contains:与contains相反。 memberOf:判断某个Fact属性值是否在某个集合中,与contains不同的是他被比较的对象是一个集合,而contains被比较的对象是单个值或者对象。 not memberOf:正好相反。 matches:正则表达式匹配,与java不同的是,不用考虑'/'的转义问题 not matches:正好相反。
规则的结果部分 当规则条件满足,则进入规则结果部分执行,结果部分可以是纯java代码,比如: then System.out.println("OK"); //会在控制台打印出ok end 当然也可以调用Fact的方法,比如 $message.execute();操作数据库等等一切操作。 结果部分也有drools提供的方法: insert:往当前workingMemory中插入一个新的Fact对象,会触发规则的再次执行,除非使用no-loop限定; update:更新 modify:修改,与update语法不同,结果都是更新操作 retract:删除 RHS部分除了调用Drools提供的api和Fact对象的方法,也可以调用规则文件中定义的方法,方法的定义使用 function 关键字 functionvoidconsole { System.out.println(); StringUtils.getId();// 调用外部静态方法,StringUtils必须使用import导入,getId()必须是静态方法 } Drools还有一个可以定义类的关键字: declare可以再规则文件中定义一个class,使用起来跟普通java对象相似,你可以在RHS部分中new一个并且使用getter和setter方法去操作其属性。 declare Address @author(Cx) // 元数据,仅用于描述信息 @createTime(2017-1-24) city : String @maxLengh(100) postno : int end 上述的'@'是什么呢?是元数据定义,用于描述数据的数据~,没什么执行含义 你可以在RHS部分中使用Address address = new Address()的方法来定义一个对象。