drools基本知识

一、概述

kie(Knowledge Is Everything)

package rules.rulesHello  //规则逻辑路径
   rule "test001"  //rule 规则开始 "test001" 规则名
         when
               eval(true);  //规则条件
         then
             System.out.println("hello world"); //规则返回结果
    end  //规则结束

规则文件内容包含三大块 :包路径,引用,规则体(核心)

规则体:分为 LHS,RHS两大功能模块

1.LHS(Left Hand Side):条件部分,when与then中间部分

2.RHS(Right Hand Side):结果部分,then与end中间部分

Drools规则引擎中传递的数据,术语称Fact对象,Fact对象是一个普通的javaBean,规则体可以对当前对象进行任何的读写操作。Fact插入Working Memory(内存储存)


<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
   <kbase name="rules" packages="rules.rulesHello">
       <ksession name="testhelloWorld"/>
   </kbase>
</kmodule>

(1)一个kmodule.xml配置可以包含多个kbase

(2)kbase的packages属性,值为src/main/resources目录下文件夹名称,可以同时定义多个包,以逗号进行分隔。可以包含多个ksession

(3)每个ksession,名称可以是任意字符,不能重复

(4)packages指定的所有规则文件都会读取,子目录中规则文件不会被加载


@Test
   public void test2(){
       //单例模式创建KieServices,可以访问所以KIE构建和运行时的接口,初始化过程
       KieServices kieServices = KieServices.Factory.get();
       //KieContainer读取路径中需要构建的文件,是KIE的容器,初始化过程、、、、
       //创建KieModule,KieBase,KieSession对象,KieModule和KieBase只会创建一次
       KieContainer kc = kieServices.getKieClasspathContainer();
       //新建一个KIE会话
       KieSession ks = kc.newKieSession("testhelloWorld");
       Person person=new Person();
       person.setName("zhangsan");
       person.setAge(12);
       FactHandle insert = ks.insert(person);
       System.out.println(insert);
       //执行规则
       int i = ks.fireAllRules();
       System.out.println(i);
       ks.dispose();
  }

二、基础语法

规则文件关键字:

关键字概述
package 包名,只限于逻辑上的管理,若自定义的查询或函数位于同一包名,不管物理位置如何,都可以直接调用
import 规则引用问题,导入类或方法
global 全局变量
function 自定义函数
queries 查询
rule end 规则体

规则体语法结构

关键字描述
rule 规则开始,参数是规则的唯一名称
attributes 规则属性,是rule与when之间的参数,为可选项
when 规则条件部分,默认为true
then 规则结果部分
end 当前规则结束

pattern(匹配模式)

规则体中LHS部分绑定变量基本上两种形式:

一种:整个Fact变量的绑定


rule "rule1"
 when
 $customer:Customer(age>25,gender=='male')
 then
....
end

另一种:约束条件属性变量的绑定


rule "rule1"
 when
 $customer:Customer(age>25,$g:gender=='male')
 then
....
end

约束连接

“&&”(and) "||"(or) ","(and)

contains 比较操作符:

语法:Object(field[Collection/Array] contains|not contains value)

memberOf 比较运算符:判断某个Fact对象的某个字段是否在一个或多个集合中

语法:Object(fieldName memberOf|not memberOf value[Collection/Array])

matches比较运算符:用来对某个Fact对象的字段与标准的Java正则表达式进行相似匹配

语法:Object(fieldName matches|not matches "正则表达式")

soundslike比较运算符:用来检查单词是否具有与给定值几乎相同的声音(使用英语发音)

语法:Object(fieldName soundslike 'value')

str 比较运算符:检查String字段是否以某一值开头/结尾,还可以判断字符串长度

语法:Object(fieldName str[startsWith|endsWith|length])

三、规则属性

1.no-loop

默认值:false

类型:Boolean。

属性说明:防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使规则再次被激活,从而导致死循环。

2.ruleflow-group

默认值:N/A

类型:String

属性说明:ruleflow-group分为rule、flow和group3个部分,分别代表规则、流程、分组,即常说的规则流。

3.lock-on-active

默认值:false

类型:Boolean

属性说明:lock-on-active是指“锁定活跃”

4.salience

默认值:0

类型:integer

属性说明:规则体被执行的顺序,每一个规则都有一个默认的执行shunxu,如果不设置sailence属性,规则体的执行顺序为由上到下。salience值可以是一个整数,也可以是个负数,值越大,执行顺序越高,排名靠前。

5.enabled

默认值:true

类型:Boolean

属性说明:指规则是否可以被执行,若规则体设置为enabled false,则规则体将视为永久不被激活

6.dialect

可能值:Java或Mvel

类型:String

属性说明:用来定义规则中要使用的语言类型,支持Mvel和java两种类型的语言

7.date-effective

默认值:N/A

类型:String、日期、时间

属性说明:只有当前系统时间大于等于设置的时间或日期,规则才会被激活。在没有设置该属性的情况下,规则体不受时间限制。可接受日期格式“dd-MMM-yyyy" 如:date-effective “25-October-2019"

8.date-expires

默认值:N/A

类型:String、日期、时间

属性说明:date-expires属性与date-effective属性相反,只有当前系统时间小于设置的时间或日期,规则才会激活 修改日期格式:通过 System。setProperty(“drools.dateformat","yyyy-MM-dd HH:mm:ss")

9.duration

默认值:无

类型:long

属性说明:表示定时器,如果当前规则LHS部分为true,那么规则继续执行;如果该属性已经被弃用,那么通过新的属性timer来控制

10.activation-group

默认值:N/A

类型:String

属性说明:activation-group是指激活分组,通过字符串定义分组名称,具有相同组名称的规则体有且只有一个规则被激活,其他规则体的LHS部分仍然为true也不会再被执行。该属性受salience属性的影响,如当前规则文件中的其他规则未设计该属性,则视为规则处于被激活状态,并不受该属性的影响。

11.agenda-group

默认值:无,需要通过Java设置

类型:String

属性说明: agenda-group是议程分组,属于另一种可控的规则执行方式,是指用户可以通过配置agenda-group的参数来控制规则的执行,而且只有获取焦点的规则才会被激活。


ks.getAgenda().getAgendaGroup("ag1").setFocus();//让AgendaGroup分组为ag1的获取焦点

12.auto-focus

默认值:false

类型:boolean

属性说明:auto-focus属性为自动获取焦点,即当前规则是否被激活。如果一个规则被执行,那么认为auto-focus为true;如果单独设置,一般结合agenda-group,当一个议程组未获取焦点时,可以设置auto-focus来控制

13.timer

默认值:无

类型:与java定时器参数类型相似

属性说明:timer是一个定时器,用来控制规则的执行时间,两种写法:


//第一种
timer(int:<initial delay> <repeat interval>?)
timer(int: 30s)
timer(int: 30s 5m)
//第二种
timer(cron: <cron expression>)
timer(cron: * 0/15 * * * ?)

四、中级语法

1.global全局变量

1.常量值是不能改变的

2.包装类是不能改变的

3.类似javaBean、List类的操作是可以改变内容的,但内存地址不变

2.query查询

以query开始、以end结束


package rules.rulesHello
import com.mufeng.rules.pojo.Person;
//"person age is 30 and name is 张三" 名称
// (String $name) 参数 (多个可以用","分隔)
query "person age is 30 and name is 张三" (String $name)
    person:Person(name==$name,age==30)
end

3.function函数

规则中函数有两种形式:

一种:在规则中添加关键字function


package rules.isFunction
rule "function1"
   when
   then
    System.out.println(function1("王二"));
    end

function String function1(String name){
System.out.println("name:"+name);
return name;
}

另一种:import,引用java静态方法

4.declare声明

功能:1.声明新类型,2.声明元数据类型

package rules.rulesHello

declare Person1 extends com.mufeng.rules.pojo.Person //声明 extends加继承
   type:String
end

rule "de1"
when
then
Person1 p=new Person1();
p.setName("张三");
p.setType("2");
insert(p);
end
rule "de"
when
$p:Person1(name=="张三")
then
  System.out.println($p.getType());
  System.out.println($p);
end

4.规则when

对象属性有3中类型的限制:单值限制、复合值限制和多限制

单值限制:(name=="张三")

1.复合值限制in/not in

Person(className in ("一班","二班",$cn))

2.条件元素eval

eval(expression) :任何语义代码,并返回一个boolean类型

3.条件元素not

判断工作内存中是否存在某个值,如 not Person();

4.条件元素exists

与not相反,判断工作内存中存在某个值,如 exists Person();

5.条件元素forall

与eval()功能相似,通过模式匹配对forall进行判断,当完全匹配是,forall为true。


forall(p:Person(name=="张三") Person(this==p,age==30))

6.条件元素from

可以让用户指定任意的资源,用于LHS部分的数据匹配,也可以用来对集合进行遍历,还可以用来对java服务进行访问并就结果进行遍历 如 from listFrom("张三",10) listFrom为静态方法,返回list集合

7.条件元素collect

需要结合from来使用 from collect 用来汇总的

8.条件元素accumulate(功能强大)

允许规则迭代整个对象的集合,为每个元素定制执行动作,并在结束时返回一个结果对象,支持预定义的累积函数的使用,也可以使用其他内置函数,还可以使用自定义函数进行特殊化操作。

内置包括:average(平均值)、min(最小值)、max(最大值)、count(统计)、sum(求和)、collectList(返回List)、collectSet(返回HashSet)

inline的语法结构:


<result pattern> from  accumulate(<source patterm>,init(<init code>),action(<action code>),reverse(<reverse code>),result(<result expression>))

自定义定制:新建 TestAccumulate并实现AccumulateFunction目录为com/rulesAccumulate

9.条件元素规则继承

与java相似,


rule "No2" extends "No1"

10.条件元素do对应多then同条件


rule "test"
 when
  $p:Person(name=="张三")
  do[then03]
  do[then03]
 then
   System.out.println("......");
 then[then01]
   System.out.println("******");
 then[then03]
   System.out.println("******");
end

1.使用do时,do的参数与then的参数必须有对应关系。

2.then可以不与do成对出现

3.使用do时,do后的参数在RHS中是必须要存在的,参数是一个zhizhen。

4.使用修改时,在非update情况下,then部分都会被执行。

5.使用修改时,在update情况下,then部分是有优先级的,是根据do的顺序控制的,但没有参数的then可能会改变其他的RHS部分。

6.使用do时,顺序控制是至关重要的。

7.无参数的then,优先级可能会低于指定的do。

8.do只能在其他条件元素之后使用。

5.规则then

操作命名:

update(Fact事实对象)

insert(new Object())

insertLogical(new Object())

delete(handle)

modify(<fact-expression>){

<expression>[,<expression>]*

}


modify($p){
   setAge(50),
   setName("李四")
}

drools.halt():立即终止规则执行。

drools.geWorkingMemory():返回WorkingMemory对象。

drools.setFocus(String s):将焦点放在指定的议程组上。

drools.getRule().getName():返回规则的名称。

drools.getTule():返回与当前正在执行的规则匹配的数组,并且为drools.getActivation()提供相应的激活

6.kmodule配置说明

kmodule.xml文件放到src/main/resources/META-INF/文件夹下


<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
   <kbase name="rules" packages="rules.rulesHello">
       <ksession name="testhelloWorld"/>
   </kbase>
   <kbase name="query" packages="rules.isQuery">
       <ksession name="isQuery"/>
   </kbase>
   <kbase name="function" packages="rules.isFunction">
       <ksession name="isFunction"/>
   </kbase>
</kmodule>

五、KieSession状态

有状态的KieSession:

需要清理KieSession的状态,调用dispose()方法,如果在调用规则时不调用dispose()方法,则KieSession.insert(Object)会产生迭代方法插入的(笛卡尔积)

无状态的StatelessKieSession

execute()默认调用dispose()方法

六、Drools高级用法

1.决策表

 注释行:package包路径 
关键字 RuleSet rulesTwo.isXls  
关键字 RuleTable 测试规则    
关键字 CONDITION ACTION  
条件区      
条件区 eval(true); System.out.println("$param");  
条件注释行      
规则值说明   测试规则_7  
规则值说明   测试规则_8  
规则值说明   测试规则_9  

1.RuleSet和drl文件中package功能是一样的,为必填项

2.RuleTable和drl文件中规则名称的功能是一样的,为必填项

3.CONDITION和规则体中LHS部分功能是一样的,为必填项

4.ACTION和规则体中RHS部分功能是一样的,为必填项

检查决策表生成drl文件是否正确


<dependency>
   <groupId>org.drools</groupId>
   <artifactId>drools-decisiontables</artifactId>
   <version>${drools.version}</version>
</dependency>

@Test
public void test7() throws FileNotFoundException {
   File file=new File("D:\Development\idea\workspace\spring\boot\drools-test\src\main\resources\rulesTwo\isXls.xls");
   InputStream fileInputStream = new FileInputStream(file);
   SpreadsheetCompiler spreadsheetCompiler = new SpreadsheetCompiler();
   String compile = spreadsheetCompiler.compile(fileInputStream, InputType.XLS);
   System.out.println(compile);
}

占位符: 1、$2

2.DSL领域语言(略)

3.规则模板

cheese.xls

     
  年龄 className log  
  50 一班 1  
  40 二班 2  
  30 三班 3  
  20 四班 4  
         

cheese.drt


template header
age
className

package rulesTwo.isDrt;
import com.mufeng.rules.pojo.Person;

template "cheesefans"

rule "cheese fans_@{row.rowNumber}"
no-loop true
  when
    $p:Person(age==@{age})
  then
    $p.setClassName("@{className}");
    update($p);
end
end template

规则模板文件以template header开头,以end template结尾 age表示Excel文件的列 相当于占位符


<kbase name="isDrt" packages="rulesTwo.isDrt">
   <ruleTemplate dtable="rulesTwo/isDrt/cheese.xls" template="rulesTwo/isDrt/cheese.drt" row="3" col="2"/>
   <ksession name="isDrt"/>
</kbase>

row="3" 从第三行取数据 col="2" 从第二行取数据


@Test
public void test8(){
   KieServices kieServices = KieServices.Factory.get();
   KieContainer kc = kieServices.getKieClasspathContainer();
   KieSession ks = kc.newKieSession("isDrt");
   Person person=new Person("张三",50);
   ks.insert(person);
   int i = ks.fireAllRules();
   System.out.println(i);
   System.out.println(person.getClassName());
   ks.dispose();
}

第二种获取方法:


@Test
public void test9(){
   
   ObjectDataCompiler converter = new ObjectDataCompiler();
   Person person=new Person();
   person.setAge(50);
   person.setClassName("一班");
   List<Person> cfl=new ArrayList<>();
   cfl.add(person);
   InputStream inputStream =null;
   try {
       inputStream=ResourceFactory.newClassPathResource("rulesTwo\isDrt\cheese.drt", Test1.class).getInputStream();
  } catch (IOException e) {
       e.printStackTrace();
  }
   String drl = converter.compile(cfl, inputStream);
   System.out.println(drl);
   KieHelper kieHelper=new KieHelper();
   kieHelper.addContent(drl, ResourceType.DRL);
   KieSession kieSession = kieHelper.build().newKieSession();
   Person person1=new Person();
   person1.setAge(50);
   person1.setName("张三");
   kieSession.insert(person1);
   int i = kieSession.fireAllRules();
   System.out.println(i);
   kieSession.dispose();
}

4.规则流(略)

5.Drools事件监听

RuleRuntimeEvenListener,AgendaEventListener,ProcessEventListener3个接口

七、Workbench

1.安装与配置

1.安装jdk

2.安装tomcat

http://tomcat.apache.org/download-70.cgi

3.下载Workbench的war包,http://www.drools.org/download/download.html

安装说明:

(1)将war包放在webapps/目录下,并改名为kie-wb.war

(2)将下列jar复制到TOMCAT_HOME/lib中:

btm-2.1.4.jar

btm-tomcat55-lifecycle-2.1.4.jar

h2-1.3.161.jar

jta-1.1.jar

slf4j-api-1.7.2.jar

slf4j-jdk14-1.7.2.jar

log4j-api-2.1.jar

log4j-slf4j-impl-2.1.jar


<dependency>
   <groupId>org.codehaus.btm</groupId>
   <artifactId>btm</artifactId>
   <version>2.1.4</version>
</dependency>
<dependency>
   <groupId>org.codehaus.btm</groupId>
   <artifactId>btm-tomcat55-lifecycle</artifactId>
   <version>2.1.4</version>
</dependency>
<dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
   <version>1.3.161</version>
</dependency>
<dependency>
   <groupId>javax.transaction</groupId>
   <artifactId>jta</artifactId>
   <version>1.1</version>
</dependency>
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>1.7.2</version>
</dependency>
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-jdk14</artifactId>
   <version>1.7.2</version>
</dependency>
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-api</artifactId>
   <version>2.1</version>
</dependency>
<dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-slf4j-impl</artifactId>
   <version>2.1</version>
</dependency>

(3)在TOMCAT_HOME/conf目录下,新建btm-config.properties(每个语句后面不能有空格)


bitronix.tm.serverId=tomcat-btm-node0
bitronix.tm.journal.disk.logPart1Filename=${btm.root}/work/btm1.tlog
bitronix.tm.journal.disk.logPart2Filename=${btm.root}/work/btm2.tlog
bitronix.tm.resource.configuration=${btm.root}/conf/resources.properties

在TOMCAT_HOME/conf下,新建resources.properties,


resource.ds1.className=bitronix.tm.resource.jdbc.lrc.LrcXADataSource
resource.ds1.uniqueName=jdbc/jbpm
resource.ds1.minPoolSize=10
resource.ds1.maxPoolSize=20
resource.ds1.driverProperties.driverClassName=org.h2.Driver
resource.ds1.driverProperties.url=jdbc:h2:file:~/jbpm
resource.ds1.driverProperties.user=sa
resource.ds1.driverProperties.password=
resource.ds1.allowLocalTransactions=true

(4)在TOMCAT_HOME/bin目录下,新建setenv.sh


CATALINA_OPTS="-Xmx512M - XX:MaxPermSize=512m -Dbtm.root=$CATALINA_HOME
-Dbitronix.tm.configuration=$CATALINA_HOME/conf/btm-config.properties
-Djbpm.tsr.jndi.lookup=java:comp/env/TransactionSynchronizationRegistry
-Djava.security.auth.login.config=$CATALINA_HOME/webapps/kie-web/WEB-INF/classes/login.config
-Dorg.jboss.logging.provider=jdk
-Dorg.jbpm.cdi.bm=java:comp/env/BeanManager
-Dorg.guvnor.m2repo.dir=/root/.m2/repository
-Dorg.kie.demo=false
-Dorg.kie.example=false"

(5)配置JEE security

把下面3个jar包放到TOMCAT_HOME/lib下


<dependency>
   <groupId>javax.security.jacc</groupId>
   <artifactId>javax.security.jacc-api</artifactId>
   <version>1.5</version>
</dependency>
<dependency>
   <groupId>org.kie</groupId>
   <artifactId>kie-tomcat-integration</artifactId>
   <version>${drools.version}</version>
</dependency>
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>1.7.2</version>
</dependency>

(6)在TOMCAT_HOME/conf/server.xml的Host节点最后添加


<Value className="org.kie.integration.tomcat.JACCValve"/>

(7)编辑TOMCAT_HOME/conf/tomcat-users.xml,添加‘analyst'或’admin‘角色,添加KIE-WB相应的用户


<role rolename="admin"/>
<role rolename="analyst"/>
<user username="kie" password="kie" roles="admin"/>
<user username="kie-analyst" password="kie-analyst" roles="analyst"/>

(8)启动tomcat,访问 “8080/kie-wb" perfect

 

原文地址:https://www.cnblogs.com/mufeng07/p/12626251.html