Drools学习笔记
第一天
简介
Boss Rules 的前身是Codehaus的一个开源项目叫Drools。最近被纳入JBoss门下,更名为JBoss Rules,成为了JBoss应用服务器的规则引擎。
术语简称
Package:
包名,必须填写,放在规则文件的第一行,名字随意,不必对应物理路径
Import:
导入的外部变量,可以是一个类,也可以是一个静态方法
Rule:
定义一个规则,一个规则可以包括三部分
属性部分:定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等
条件部分:即LHS,定义当前规则的条件。
结果部分:即RHS,这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用。
环境搭建
先创建一个maven项目,修改pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>Drools</groupId> <artifactId>Drools_demo1</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> <version>7.6.0.Final</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.6.0.Final</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project> |
然后创建resources文件夹下创建helloworld.drl文件
//包名 package helloworld; //导入的外部变量 import domain.Message; //规则 rule "HelloWorld" //LHS when m:Message($name : name == Message.HELLO) //RHS then System.out.println(m.getMsg() + $name); end |
然后创建封装类Message.java
package domain;
import java.io.Serializable;
/** * @author WangBo * @date 2018/10/29 14:16 * @description */ public class Message implements Serializable {
public static String HELLO = "hello";
public static String HI = "hi";
public static String HEI = "hei";
private String name;
private String msg;
private Long id;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getMsg() { return msg; }
public void setMsg(String msg) { this.msg = msg; }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Override public String toString() { return "Message{" + "name='" + name + '\'' + ", msg='" + msg + '\'' + ", id=" + id + '}'; } } |
最后创建测试类,运行我们第一个程序
import domain.Message; import org.junit.Test; import org.kie.api.KieServices; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession;
/** * @author WangBo * @date 2018/10/29 09:47 * @description */ public class HelloWorldTest { @Test public void testHelloWorld() { KieServices kieServices = KieServices.Factory.get(); KieContainer kieContainer = kieServices.newKieClasspathContainer(); KieSession kieSession = kieContainer.newKieSession("helloWorldSession"); Message message = new Message(); message.setMsg("这是第一个demo "); message.setName(Message.HELLO); kieSession.insert(message); kieSession.fireAllRules(); kieSession.dispose(); } } |
查询元素
判断:
判断其实和常用的符号差不多,”==”、”!=”、”>=”、”<=”、”&&”、”||”、“,”
之前的例子中,就有name的判断
赋值:
Drools的赋值是通过‘:’表示的,前面的是变量,后面的是数值,一般我们习惯将变量以‘$’开头,便于区分,但是在开发中有些人也喜欢省略它。
还是上面的例子,意思是如果Bean中的name属性等于Message.HELLO,则将name值赋给$name中
exists:
判断这个对象是否存在
not:
和exists正好相反,判断这个对象是否不存在
from:
From表示一个集合中是否存在一个或多个满足指定条件的对象,每存在一个满足条件的对象,执行一次then操作
我们把上面的例子稍稍修改了一下,将一个装有Message对象的集合放进来,然后我们找到这个集合中name为Message.HELLO的对象
collect:
Collect与from有些相似,不同的是,collect返回的是一个集合,而from是一个个对象
我们再将上面的例子修改一下,将这个集合中所有name为Message.HELLO的对象放入一个集合中,如果返回的集合size大于0,把他们打印出来
accumulate:
Accumulate有点点像SQL中的聚合函数,用来求出集合的某些数值(average、min、max、count、sum等等);然后我们再修改一下上面的例子,这次是计算满足条件的个数,并把它们打印出来
字段约束连接
执行顺序:
&&、||、‘,’ 下面我们继续改例子,传入的Message的id大于15或者name为Message.HELLO且msg为demo的对象显示出来
contains:
contains主要是判断集合中是否存在对象,下面这个demo就是判断传入的Message是否在List集合当中
not contains:
和contain相反,这里就不说废话做介绍了
memberOf:
和contains相似,判断对象是否属于集合,下面小例子就是传入的Message是否属于集合(注意和contains的区别)
not memberOf:
和memberOf相反
matches:
表达式匹配,下面例子就是判断msg是否以"Demo"开头的
not matches:
与matches相反
RHS
update:
顾名思义,更新操作,如果Message以Demo开头,将其msg赋值Test_01(任何insert、update、retract操作都会引起规则的重新匹配)
insert\retract:
//TODO 和update大同小异,之后补充
modify:
更改代码块,例子如下,如果符合表达式,将Message修改对应内容(这里不用update,modify已经帮你做了)
13个属性
salience:
用于设置优先级,值越大,优先级越高,默认是0,不设置则随机执行规则,下面的例子,先执行3后执行1
no-loop:
控制已经执行的规则在条件再次满足时是否会再次被执行,默认为false,当其为true时,该规则只会被检查一次,忽略fact更新导致的再次检测规则
date-effective:
控制时间只有在到达后才会触发,默认格式为 dd-MMM-yyyy
date-expires:
与date-effective正好相反,默认格式为 dd-MMM-yyyy
enabled:
判断规则是否可用,默认为true
duration:
指定规则将在指定的值后的另一个线程触发,值为Long,单位毫秒
activation-group:
具有相同activation-group属性的规则,只会有一个被执行,配合salience属性确定哪个被执行
agenda-group:
在执行fireAllRules之前,所有的规则以及Fact都存在Agenda中,agenda-group对Agenda进行了分组,对于设置了agenda-group的规则,需要得到focus才能执行,可以设置auto-focus,则不需要进行验证
测试类:
DRL文件:
lock-on-active:
和no-loop一样,用于agenda-group当中
dialect:
有两种格式,Java和mvel