drools集成springboot

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());

可以看到:
输出的debug日志
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, 即规则的动态编译。
如果觉得这篇文章帮助了您,欢迎点赞和评论,有问题也欢迎在评论区指出,您的支持是我创作的动力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章