这里小编就针对session而言,单独拿出一个章节来讲session,因为这个在实际应用中是非常重要的。定义了一个像前一个示例中的一个kmodule.xml,现在可以使用他们的名字从KieContainer中简单地检索KieBase和KieSessions。
从KieContainer抢走KieBases和KieSessions
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
KieBase kBase1 = kContainer.getKieBase("KBase1");
KieSession kieSession1 = kContainer.newKieSession("KSession2_1");
StatelessKieSession kieSession2 = kContainer.newStatelessKieSession("KSession2_2")
必须注意的是,由于KSession2_1和KSession2_2有2种不同的类型(第一种是有状态的,而第二种是无状态的),所以有KieContainer必要根据其声明的类型调用2种不同的方法 。如果所KieSession 请求的类型KieContainer与kmodule.xml文件中声明的类型不符,KieContainer将抛出一个RuntimeException。此外,由于KieBase和KieSession被标记为默认值,它可以从KieContainer没有传递任何名称的情况下获得它们。
小编为什么会要将session独立出来一个章节呢,这是有原因的,我们在开发过程会遇到各种情况,这个session的状态是很重要的,也会在开发中经常使用。
KieSession用于与规则引擎进行交互的会话。
会话分为两类:
KieSession 有状态的
KieSession 会在多次与规则引擎进行交互中,维护会话的状态。
定义 KieSession,在kmodule.xml文件中定义 type 为stateful的 session:
注意:stateful 是 type 属性的默认值。
获取 KieSession实例
KieSession statefulSession = kieContainer.newKieSession("stateful_session");
接下来,可以在 KieSession执行一些操作。最后,如果需要清理 KieSession维护的状态,调用 dispose()方法。
这里有状态的值插入数据是通过ksession.insert(Object) 迭代方式插入的(笛卡尔积),请注意,迭代方式。怎么理解呢,举个例子:
Ksession.insert(obj1)
Ksession.insert(obj2)
这是两个不同的对象值,通过这样的方式,在rule中进行应用,后续还会使用更多次的有状态的应用例子,读者仔细体会
StatelessKIESession 无状态的
与 KieSession相反,StatelessKIESession 隔离了每次与规则引擎的交互,不会维护会话的状态,所以保证了数据的正确性,比较适用于高并发,多线程之类的互联网项目。
如果将 session 比作编程语言中的函数,StatelessKIESession 就是无副作用的函数。
定义 StatelessKIESession,在kmodule.xml文件中定义type为stateless的 session:
如果我们想要用无状态的kie-session的话 就必须这样定义了。
该StatelessKieSession包装的 KieSession,而不是扩展它。其主要重点是决策服务类型场景。它避免了调用的需要 dispose()。无状态会话不支持迭代插入和fireAllRules()来自Java代码的方法调用; 调用的行为execute()是一个单一的方法,将内部实例化一个KieSession,添加所有用户数据并执行用户命令,调用 fireAllRules(),然后调用dispose()。虽然使用这个类的主要方式是通过接口支持的BatchExecution(一个子接口Command),但是CommandExecutor当简单的对象插入是必需的时候,提供了两种方便的方法。
获取 StatelessKIESession 实例:
StatelessKieSession statelessKieSession = kieContainer.newStatelessKieSession("stateless_session");
//通过 KieServices 获取 command 工厂类 KieCommands:
KieCommands commandFactory = kieServices.getCommands();
//可以使用工程类 KieCommands 调用 newXXXCommand 开头的方法创建 command 实例。
//会话执行 command:
statelessKieSession.execute(command);
//----------------------- 分隔线-----------------------
[source code] 调用的是该接口
public interface StatelessRuleSession {
void execute(java.lang.Object o);
void execute(java.lang.Iterable iterable);
}
StatelessKnowledgeSessionImpl 实现类
public void execute(Object object) {
StatefulKnowledgeSession ksession = newWorkingMemory();
try {
ksession.insert( object );
ksession.fireAllRules();
} finally {
dispose(ksession);
}
}
从代码中我们可以看出来,也是通过finally中的dispose方法来删除的,只是与kieSession方式不同。
StatelessKieSession ksession = kbase.newStatelessKieSession();
List cmds = new ArrayList();
cmds.add( CommandFactory.newInsert( new Cheese( "stilton", 1), "stilton") );
cmds.add( CommandFactory.newStartProcess( "process cheeses" ) );
cmds.add( CommandFactory.newQuery( "cheeses" ) );
ExecutionResults bresults = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );
QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );
在上面的例子中,执行多个命令,其中两个填充ExecutionResults。query命令默认使用与查询名称相同的标识符,但也可以映射到不同的标识符。所有命令都支持使用XStream的XML和jSON编组,以及JAXB编组。命令API 部分将介绍这一点。
如果获取这些批处理或只通过execute的值呢,仔细的你一定会发现,这里不是有标识嘛,Cheese stilton = ( Cheese ) bresults.getValue( "stilton" );是的,获取值是可以通过这样的方式的,后面在kie-server高级应用的时候会讲到。