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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM