Drools學習二
開始第一個工程
Drools版本:7.19.0.Final
Spingboot版本:2.1.4.RELEASE
引入依賴
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.19.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.19.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.19.0.Final</version>
</dependency>
創建實體類
這裏以任務實體爲例
public class Person {
private String name;
private int age;
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Person(String name,int age) {
this.name=name;
this.age=age;
}
}
書寫規則文件
在src/main/resources文件下,創建rules文件夾存放我們的規則文件,創建test.drl.
//created on: 2019-4-7
package com.demo //package任意的
import com.demo.test.entity.Person; //import語句,引入創建的實體
rule "isAdult"
when
person:Person(age>=18)
then
System.out.println("This is an adult");
person.setDesc("adult");
end
添加配置文件
在src/main/resources文件夾下創建META-INF文件夾,在該文件夾下創建kmodule.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns ="http://www.drools.org/xsd/kmodule">
<kbase name ="rules">
<ksession name ="ksession-rules"/>
</kbase>
</kmodule>
創建測試類
OneTest.java
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.demo.test.entity.Person;
public class OneTest {
public static void test() {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rules");
Person person =new Person("Jhon",20);
kSession.insert(person);
kSession.fireAllRules();
System.out.println(person.getDesc());
}
}
啓動類Test1Application.java
package com.demo.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.demo.test.service.OneTest;
@SpringBootApplication
public class Test1Application {
public static void main(String[] args)
SpringApplication.run(Test1Application.class, args);
OneTest.test();
}
}
運行結果
可以看到規則觸發,打印出了"This is an adult" , person的desc屬性也被賦值爲"adult"。
添加規則觸發事件和debug打印:
//RuleRuntimeEventManager規則觸發事件
kSession.addEventListener(new DefaultAgendaEventListener() {
public void afterMatchFired(AfterMatchFiredEvent event) {
super.afterMatchFired(event);
System.out.println("命中:"+event);
}
});
//提供debug打印功能
kSession.addEventListener(new DebugRuleRuntimeEventListener());
可以看到:
Fact對象是指在使用Drools 規則時,將一個普通的JavaBean對象(上例中爲Person)插入到規則引擎的 WorkingMemory當中的對象。debug日誌打印出了Fact對象的信息。
當Fact對象插入到WorkingMemory當中後,會與當前WorkingMemory當中所有的規則進行匹配,同時返回一個FactHandler對象。FactHandler對象是插入到WorkingMemory當中Fact對象的引用句柄,通過FactHandler對象可以實現對Fact對象的刪除及修改等操作。
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rules");
//RuleRuntimeEventManager規則觸發事件
kSession.addEventListener(new DefaultAgendaEventListener() {
public void afterMatchFired(AfterMatchFiredEvent event) {
super.afterMatchFired(event);
System.out.println("命中:"+event);
}
});
//提供debug打印功能
kSession.addEventListener(new DebugRuleRuntimeEventListener());
Person person =new Person("Jhon",20);
FactHandle handle =kSession.insert(person); // 獲取FactHandle
System.out.println(handle);
kSession.fireAllRules();
System.out.println(person.getDesc());
打印結果爲:org.drools.core.impl.StatefulKnowledgeSessionImpl$O
bjectStoreWrapper@58606c91
有一點需要記住的是,當一個普通的Java Bean插入Working Memory中,每次規則fire完是不會釋放的,drools本身耗內存,大量的堆積可能導致溢出。
通過句柄進行Fact對象的delete操作:
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rules");
//RuleRuntimeEventManager規則觸發事件
//kSession.addEventListener(new DefaultAgendaEventListener() {
// public void afterMatchFired(AfterMatchFiredEvent event) {
// super.afterMatchFired(event);
// System.out.println("命中:"+event);
// }
// });
//提供debug打印功能
//kSession.addEventListener(new DebugRuleRuntimeEventListener());
Person person =new Person("Jhon",20);
FactHandle handle =kSession.insert(person); // 獲取FactHandle
kSession.fireAllRules();
kSession.delete(handle); //移除句柄
kSession.dispose(); //銷燬kSession
對於插入多個對象的情況,可以直接獲取KieSession對應的所有已插入的FactHandle對象的集合。
Collection<FactHandle> HandleList = kieSession.getFactHandles();
釋放KieSession中的句柄可以調用下面的封裝函數:
/**
* 移除KieSesion中的FactHandle
* @param kieSession
*/
public static void removeFactHandle(KieSession kieSession) {
if(null==kieSession)
return;
Collection<FactHandle> HandleList = kieSession.getFactHandles();
Iterator<FactHandle> Iterator = HandleList.iterator();
while(Iterator.hasNext()) {
kieSession.delete(Iterator.next());
}
}
關於FactHandle部分詳細的介紹,可以參考官方文檔。
工程源碼
下載鏈接:鏈接:https://pan.baidu.com/s/1aa-CdOiaPdlV7rLzp3Tlaw
提取碼:14pl
結語
在下節中,將介紹不通過配置kmodule.xml和drl文件的方式進行規則的fire, 即規則的動態編譯。
如果覺得這篇文章幫助了您,歡迎點贊和評論,有問題也歡迎在評論區指出,您的支持是我創作的動力。