drools session理解
一、理解
在drools
中存在2种session,一种是有状态的Session (Stateful Session
),另外一种一种是无状态的Session (Stateless Session
)。
1、那么他们2者之间有什么不同呢?
2、何时该使用有状态的Session,何时该使用无状态的Session?
此处简单说一下我的理解
。
1、有状态Session
有状态 session 是使用推理对fact 对象随时间进行迭代更改的会话。 在有状态的 session中,来自 session的先前调用(先前的会话状态)的数据在会话调用之间保留,而在无状态的 session中,该数据被丢弃。
2、无状态Session
无状态 session 是不会使用推理对fact 对象随时间进行迭代更改的会话。 无状态 Session 的先前调用的数据在会话之间不会保留的。
解释:
针对无状态 session 是不会使用推理对fact 对象随时间进行迭代更改的会话
的理解,我的理解是 针对Java Api
来使用的,
1、在无状态的Session中,只有execute
方法,多次调用execute
方法,在上次execute
方法不会影响下次execute
方法的执行。
2、而在drl
文件中使用insert
或update
或modify
或delete
等方法时,会导致工作内存的对象更新,导致规则的重新匹配。
3、那么何时使用不同的Session呢?
1、如果说我们只是验证一下规则,那么用无状态的Session。 比如:
- 验证用户是否有开银行卡的条件。
- 计算订单金额的折扣。
即一步就可以完成。
2、如果说我们的规则需要多步来完成,则可以用有状态的Session。 比如:
- 向Session中插入Fact对象A,然后触发规则。
- 执行一段Java代码
- 向Session中插入Fact对象B,然后触发规则,此时的规则需要依赖上一步规则的数据。
即需要关联的多步来完成。
二、需求
我们自己有一个Count
对象,该对象存在cnt
和name
2个属性。
规则文件中存在如下2个规则
规则一:
如果工作内存中存在Count
对象,则将Count
对象的cnt
属性加1
规则二:
如果工作内存中存在2
个Count
对象,一个对象的name=count-01
另一个对象的name=count-02
则输出ok
字符串。
针对有状态Session和无状态Session,看结果有什么不同。
三、实现步骤
1、项目结构说明
2、引入jar包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<type>pom</type>
<version>7.69.0.Final</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
3、编写Count类
@Data
@AllArgsConstructor
public class Counter {
/**
* 名称
*/
private String name;
/**
* 计数
*/
private Integer cnt;
}
就是一个普通的java对象。
4、编写kmodule.xml文件
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kabse-01" packages="rules.stateful" default="false">
<!--
type="stateful" 表示有状态的session
-->
<ksession name="stateful-session" default="false" type="stateful"/>
</kbase>
<kbase name="kabse-02" packages="rules.stateless" default="false">
<!--
type="stateless" 表示无状态的session
-->
<ksession name="stateless-session" default="false" type="stateless"/>
</kbase>
</kmodule>
此处需要注意ksession
中type
的值,无状态Session和有状态Session的值不一致,不写type,默认就是有状态Session。
5、编写规则文件
package rules.stateful
import com.huan.drools.Counter
// 将counter中的cnt的值递增一下
rule "stateful_rule_count_increment"
when
$counter: Counter( )
then
$counter.setCnt($counter.getCnt() + 1);
System.out.println("rule_count_increment: count name:[" + $counter.getName()+"],cnt=[" + $counter.getCnt() + "]");
end
// 如果工作内存中同时存在 count-01 和 counter-02 则输出ok
rule "stateful_rule_count_exists"
when
Counter(name == "count-01") and Counter(name == "count-02")
then
System.out.println("ok");
end
6、Stateful session运行结果
1、因为是有状态的Session,在多次
fireAllRules
的时候,上次插入到工作内存的对象还是存在的。即Session的数据保留了
。
2、有状态Session在执行完之后,必须要调用dispose
方法,避免内存泄漏。
7、Stateless Session运行结果
无状态的Session,因为会丢失Session的数据,所以
ok
没有输出出来。
四、注意事项
1、在drl
文件中,使用insert\update\modify\delete
等方法时,都在导致规则的重新匹配。
2、Java
代码中是否可以获取stateful session
或stateless session
是有ksession
中的type
的值决定的。
3、stateless session
在execute
执行完之后,会清除工作内存中的数据,而stateful session
在fireAllRules
则不会清除,除非调用了dispose
方法。
4、个人理解有状态和无状态从api层面更好理解。
五、完整代码
六、参考文档
1、docs.drools.org/7.69.0.Fina… 2、www.javainuse.com/drools_stat… 3、groups.google.com/g/drools-us…
转载自:https://juejin.cn/post/7097140449168588807