KieSession有两种不同的形式:stateless(无状态)和stateful(有状态)。大部分例子只涉及有状态的KieSession,即有状态的KieSession是到目前为止是Drools支持的最强大的会话类型。

在决定要使用哪种类型的会话之前,需要了解这两种会话类型之间的区别和相似之处。为了这样做,我们将从最简单的会话开始: 无状态KieSession.

无状态会话stateless KieSession

session会话的类型由kmoudle.xml中的定义或在编程方式中的代码实现。在大多数情况下,同一组资产(.drl文件,决策表等)可以在无状态或有状态会话中执行。

无状态的KieSession会将这种会话描述为一个函数,我们知道函数是无状态以及原子的。通常,函数是接收一组预先定义的参数,处理它们,并生成输出或结果。

在许多编程语言中,函数的结果可以是返回值本身,也可以是一些输入参数的修改。理想情况下,函数不应该具有任何间接影响,这意味着如果在同一组参数中多次调用该函数,结果应该是相同的。

无状态的KieSession与我们描述的函数有一些相同的概念:它有一些定义松散的输入参数集,它以某种方式处理这些参数,并生成响应。就像函数一样,在相同的无状态KieSession中不同的调用不会相互干扰。

为了得到一个无状态的Kie Session,我们首先需要定义KieBase来实例化它。一种方式使通过kmoudle.xml:

<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="KBase1">
    <ksession name="KSession1" type="stateless" default="true/">
</kbase>

上面代码中,我们将名为KSession1的KieSession定义为了一个无状态的会话.PS:如果不指定的话,默认就是以有状态的会话来生成那么接下来就是实例化这个名为 Ksession1的会话,我们可以使用下面的代码摘要来完成:

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
StatelessKieSession statelessKsession = kContainer.newStatelessKieSess
ion("KSession1");

暴露API的StatelessKieSession类是与KieSession对等的,通常与有状态会话进行交互的方式是:将一组事实数据插入其中,执行任何激活的规则,然后提取正在寻找的响应。在有状态的会话中,插入和执行分为两种不同的方法:insert()和 fireAllRules() 。在无状态会话的情况下,这两个方法结合成一个单独方法:execute().而这个execute()有下面三个重载版本:

execute(Object fact)
execute(Iterable facts)
execute(Command command)

前两个版本的execute(…)是将我们传递给引擎的事实数据当做参数传递进方法,触发所有激活的规则,并安排我们之前创建的会话。连续的调用者三个方法,只会重复的做着三步。请记住,在esxecute()结束后,任何与先前调用相关的内容都将被丢弃。第三个版本的execute()允许通过一个命令模式与会话进行交互.Drools已经有了一组预定义的可用命令,比如:InsertObjectCommand , SetGlobalCommand , FireAllRulesCommand 等。虽有的可用命令都可以使用CommmandFactory来创建。使用BatchExecutionCommand接口,可以将命令可以组合在一起。一个无状态的KieSession的典型用法如下代码所示:

List<Command> cmds = new ArrayList<>();
cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true
) );
cmds.add( CommandFactory.newInsert( new CustomerBuilder().withId(1L).
build(), "customer1" ) );
cmds.add( CommandFactory.newQuery( "Get Customers" "getCustomers" );
ExecutionResults results = ksession.execute( CommandFactory.
newBatchExecution( cmds ) );
results.getValue( "list1" ); // returns the ArrayList
results.getValue( "customer1" ); // returns the inserted Customer fact
results.getValue( "Get Customers" );// returns the query as a QueryResults instance

任何可以通过无状态的KieSession会话完成的事情,都可以用有状态的方法完成。使用无状态会话更像是一个显式的语句,它表示我们只是希望使用一个一次性的会话,它将用于一次性的评估。无状态会话是对无状态场景的理想选择,例如数据验证、计算(例如风险评估或抵押贷款利率)和数据过滤。由于它的无状态性,无状态的Kie Session不需要处理。在每次调用了execute()方法之后,执行的资源就会被释放。 因此,每一个execute()的执行都将于前一个是独立的,就是原子性~~总结,无状态的Kie Session是理想的无状态评估,例如:>数据验证>计算>数据过滤>消息路由>可以描述为规则的任何复杂的函数或者表达式

有状态的会话 KieSession

有状态会话与无状态会话最大区别就是,它可以在交互的同时,保持住状态。此类场景的一个常见示例是我们正在使用的一个监视进程的会话。理想情况下,我们想越快越好的向所监控的进程中插入任何传入事件,也希望尽快发现问题。在这些情况下,不能等到所有的事件都发生了(因为他们可能会永远不会停下来),所以我们可以创建一个 BatchExecutionCommand对象,在无状态会话中执行。

更好的方法是在每个事件到达时就插入,执行一个激活的规则,获取一个生成的结果,然后等待下一个事件到达。当下一次事件到来时,我们不想在一个新的会话中处理它,我们希望使用与之前的事件相同的会话。这就是有状态的会话。

当不再使用KieSession时,必须显示的调用dispose()方法。这个方法释放会话可能获得的任何资源,并释放它可能分配的任何内存。dispose()方法调用后,,会话保持在一个无效的状态,如果进一步与这个session会话进行交互,就会得到一个java.lang.IllegalS,tateException异常。

就像StatelessKieSession,KieSession接口也支持以它的execute()方法的命令模式。当我们处理持久化会话时,这个命令模式的交互是相关的。在这种情景下,所有的传递给一个单独的execute()的命令都在一个单独的事务中被执行。



无状态会话stateless KieSession和有状态的会话 KieSession插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://choupangxia.com/2021/06/07/stateless-kiesession-kiesession/