Drools 学习(二)——从HelloWorld看Drools为你做了哪些事
2015-03-01 11:46
387 查看
相信看过Drools的人一定看到过它最简单的HelloWorld的例子,接下来让我们看下它究竟为我们做了那些事情。
例子如下:
HelloWorld.java
helloWorld.drl
关于Drools规则如何编写,KModule.xml如何写,如何调用规则这些请参考Drools-6.1.0.Final_入门文档。
我想通过对源码的解析来介绍KIE API为我们方便的操控引擎做了哪些事情。
KIE的API中有以下的几个类和接口需要介绍下:
KieServices
该接口提供了很多方法,可以通过这些方法访问KIE关于构建和运行的相关对象,比如说可以获取KieContainer,利用KieContainer来访问KBase和KSession等信息;可以获取KieRepository对象,利用KieRepository来管理KieModule等。
KieServices就是一个中心,通过它来获取的各种对象来完成规则构建、管理和执行等操作。
KieContainer
可以理解KieContainer就是一个KieBase的容器。
KieBase
KieBase就是一个知识仓库,包含了若干的规则、流程、方法等,在Drools中主要就是规则和方法,KieBase本身并不包含运行时的数据之类的,如果需要执行规则KieBase中的规则的话,就需要根据KieBase创建KieSession。
KieSession
KieSession就是一个跟Drools引擎打交道的会话,其基于KieBase创建,它会包含运行时数据,包含“事实 Fact”,并对运行时数据事实进行规则运算。我们通过KieContainer创建KieSession是一种较为方便的做法,其实他本质上是从KieBase中创建出来
KieRepository
KieRepository是一个单例对象,它是一个存放KieModule的仓库,KieModule由kmodule.xml文件定义(当然不仅仅只是用它来定义)。
KieProject
KieContainer通过KieProject来初始化、构造KieModule,并将KieModule存放到KieRepository中,然后KieContainer可以通过KieProject来查找KieModule定义的信息,并根据这些信息构造KieBase和KieSession。
ClasspathKieProject
ClasspathKieProject实现了KieProject接口,它提供了根据类路径中的META-INF/kmodule.xml文件构造KieModule的能力,也就是我们能够基于Maven构造Drools组件的基本保障之一。
ClassLoader是类加载器,用来加载Java类到Java虚拟机。首先根据findParentClassLoader()获得类加载器然后把相关的父类父接口都放进类加载器中。
然后调用getKieClasspathContainer(ClassLoader loader),返回当前存在的KieContainer或者实例化一个KieContainer返回。
实例化新的Container返回:
ClasspathKieProject主要作用是根据根据类路径中的META-INF/kmodule.xml文件构造KieModule。他是什么时候进行构造呢?
是在ClasspathKieProject实例化然后传入KieContainerImpl的构造函数中:
调用的是ClasspathKieProject实现的KieProject的init()方法.
其中this.classLoader = createProjectClassLoader(parentCL)因为classLoader没怎么深入的了解,所以有点不清不楚。
比如我在META-INF中放了一个kmodule.xml,Jar包中引入了一个drools-examples-6.2.0.CR4.jar,因此里面也有一个kmodule.xml。所以在运行完后kieModules如下:
{org.drool:droolDemo:0.0.1-SNAPSHOT=FileKieModule[ ReleaseId=org.drool:droolDemo:0.0.1-SNAPSHOTfile=E:\java\workspace2\droolDemo\target\classes], org.drools:drools-examples:6.2.0.CR4=ZipKieModule[ ReleaseId=org.drools:drools-examples:6.2.0.CR4file=C:\Users\Administrator.m2\repository\org\drools\drools-examples\6.2.0.CR4\drools-examples-6.2.0.CR4.jar]}
可以看出一个是Jar包中读取到的配置文件,一个是项目中的classpath下配置文件。
源码太长不引人了,主要功能是根据上一步的到的kieModules,获得相应KieModuleModel、KieBaseModel、KieSessionModel然后放入AbstractKieProject所对应的Map以及对象中。
这些用来放Kmodule.xml中定义为default的KieBase、KieSession、StatelessKieSession。而这边只有一个对象,所以为什么默认的只有一个的缘故。当然要是有多个,newKieSession()怎么知道哪一个。
之后我们都是通过KieSession的name找到相应KieSessionModel,通过KieBase的name找到相应的KieBaseModel。然后通过相应的KieSessionModel、KieBaseModel来得到相应的KieSession以及KieBase。
在向KieSession插入fact,规则引擎首先检查的是KieSession是否还能使用。
例子如下:
HelloWorld.java
public class HelloWorldExample { public static final void main(final String[] args) { KieServices ks = KieServices.Factory.get(); KieContainer kc = ks.getKieClasspathContainer(); KieSession ksession = kc.newKieSession("HelloWorldKS"); final Message message = new Message(); message.setMessage( "Hello World" ); message.setStatus( Message.HELLO ); ksession.insert( message ); ksession.fireAllRules(); ksession.dispose(); } public static class Message { public static final int HELLO = 0; public static final int GOODBYE = 1; private String message; private int status; //.... }
helloWorld.drl
package org.drools.examples.helloworld import org.drools.examples.helloworld.HelloWorldExample.Message; rule "Hello World" dialect "mvel" when m : Message( status == Message.HELLO, message : message ) then System.out.println( message ); modify ( m ) { message = "Goodbye cruel world", status = Message.GOODBYE }; end rule "Good Bye" dialect "java" when Message( status == Message.GOODBYE, message : message ) then System.out.println( message ); end
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="HelloWorldKB" packages="org.drools.examples.helloworld"> <ksession name="HelloWorldKS"/> </kbase> </kmodule>
关于Drools规则如何编写,KModule.xml如何写,如何调用规则这些请参考Drools-6.1.0.Final_入门文档。
我想通过对源码的解析来介绍KIE API为我们方便的操控引擎做了哪些事情。
KIE的API中有以下的几个类和接口需要介绍下:
KieServices
该接口提供了很多方法,可以通过这些方法访问KIE关于构建和运行的相关对象,比如说可以获取KieContainer,利用KieContainer来访问KBase和KSession等信息;可以获取KieRepository对象,利用KieRepository来管理KieModule等。
KieServices就是一个中心,通过它来获取的各种对象来完成规则构建、管理和执行等操作。
KieContainer
可以理解KieContainer就是一个KieBase的容器。
KieBase
KieBase就是一个知识仓库,包含了若干的规则、流程、方法等,在Drools中主要就是规则和方法,KieBase本身并不包含运行时的数据之类的,如果需要执行规则KieBase中的规则的话,就需要根据KieBase创建KieSession。
KieSession
KieSession就是一个跟Drools引擎打交道的会话,其基于KieBase创建,它会包含运行时数据,包含“事实 Fact”,并对运行时数据事实进行规则运算。我们通过KieContainer创建KieSession是一种较为方便的做法,其实他本质上是从KieBase中创建出来
KieRepository
KieRepository是一个单例对象,它是一个存放KieModule的仓库,KieModule由kmodule.xml文件定义(当然不仅仅只是用它来定义)。
KieProject
KieContainer通过KieProject来初始化、构造KieModule,并将KieModule存放到KieRepository中,然后KieContainer可以通过KieProject来查找KieModule定义的信息,并根据这些信息构造KieBase和KieSession。
ClasspathKieProject
ClasspathKieProject实现了KieProject接口,它提供了根据类路径中的META-INF/kmodule.xml文件构造KieModule的能力,也就是我们能够基于Maven构造Drools组件的基本保障之一。
KieServices ks = KieServices.Factory.get()
KieServices实际上是一个接口,但是接口中有一个静态工厂用来得到实例化的KieServicesImpl.KieContainer kc = ks. getKieClasspathContainer()
得到的KieServices 通过调用方法读取配置文件然后得到Kie容器。public KieContainer getKieClasspathContainer () { return getKieClasspathContainer( findParentClassLoader() ); }
ClassLoader是类加载器,用来加载Java类到Java虚拟机。首先根据findParentClassLoader()获得类加载器然后把相关的父类父接口都放进类加载器中。
然后调用getKieClasspathContainer(ClassLoader loader),返回当前存在的KieContainer或者实例化一个KieContainer返回。
实例化新的Container返回:
public KieContainer newKieClasspathContainer(ClassLoader classLoader) { return new KieContainerImpl(new ClasspathKieProject(classLoader, listener), null); }
ClasspathKieProject主要作用是根据根据类路径中的META-INF/kmodule.xml文件构造KieModule。他是什么时候进行构造呢?
是在ClasspathKieProject实例化然后传入KieContainerImpl的构造函数中:
public KieContainerImpl(KieProject kProject, KieRepository kr) { this.kr = kr; this.kProject = kProject; kProject.init();//这才是关键 }
调用的是ClasspathKieProject实现的KieProject的init()方法.
public void init() { this.classLoader = createProjectClassLoader(parentCL); discoverKieModules(); indexParts(kieModules.values(), kJarFromKBaseName); }
其中this.classLoader = createProjectClassLoader(parentCL)因为classLoader没怎么深入的了解,所以有点不清不楚。
discoverKieModules()
很关键的一个方法,他通过两个路径KMODULE_JAR_PATH、KMODULE_SPRING_JAR_PATH来查找相应的META-INF下的kmodule.xml或者是kmodule-spring.xml,通过这两个配置文件来构造相应的kieModules。然后将得到的KieModules放入MapString[] configFiles = {KieModuleModelImpl.KMODULE_JAR_PATH, KieModuleModelImpl.KMODULE_SPRING_JAR_PATH};
比如我在META-INF中放了一个kmodule.xml,Jar包中引入了一个drools-examples-6.2.0.CR4.jar,因此里面也有一个kmodule.xml。所以在运行完后kieModules如下:
{org.drool:droolDemo:0.0.1-SNAPSHOT=FileKieModule[ ReleaseId=org.drool:droolDemo:0.0.1-SNAPSHOTfile=E:\java\workspace2\droolDemo\target\classes], org.drools:drools-examples:6.2.0.CR4=ZipKieModule[ ReleaseId=org.drools:drools-examples:6.2.0.CR4file=C:\Users\Administrator.m2\repository\org\drools\drools-examples\6.2.0.CR4\drools-examples-6.2.0.CR4.jar]}
可以看出一个是Jar包中读取到的配置文件,一个是项目中的classpath下配置文件。
indexParts(..)
protected void indexParts(Collection<InternalKieModule> kieModules,Map<String, InternalKieModule> kJarFromKBaseName);
源码太长不引人了,主要功能是根据上一步的到的kieModules,获得相应KieModuleModel、KieBaseModel、KieSessionModel然后放入AbstractKieProject所对应的Map以及对象中。
private KieBaseModel defaultKieBase = null; private KieSessionModel defaultKieSession = null; private KieSessionModel defaultStatelessKieSession = null;
这些用来放Kmodule.xml中定义为default的KieBase、KieSession、StatelessKieSession。而这边只有一个对象,所以为什么默认的只有一个的缘故。当然要是有多个,newKieSession()怎么知道哪一个。
protected final Map<String, KieBaseModel> kBaseModels; Map<KieBaseModel, Set<String>> includesInKieBase; protected final Map<String, KieSessionModel> kSessionModels;
之后我们都是通过KieSession的name找到相应KieSessionModel,通过KieBase的name找到相应的KieBaseModel。然后通过相应的KieSessionModel、KieBaseModel来得到相应的KieSession以及KieBase。
KieSession ksession = kc.newKieSession(“HelloWorldKS”);
KieSession ksession = kc.newKieSession("HelloWorldKS"); KieBase kiebase = kc.getKieBase("kieBase");
public KieSession newKieSession(String kSessionName, Environment environment, KieSessionConfiguration conf) { //传入的environment、conf都是null。KieSessionConfiguration用法在Drools6新特性中有提到过。 KieSessionModelImpl kSessionModel = (KieSessionModelImpl) getKieSessionModel(kSessionName); //DO1 验证是否找到相应的Model //DO2 验证生成Model是否是StateFul,默认生成的KieSession都是stateFul //DO3 找到相应的KieBase //DO4 根绝KieBase以及KSessionModel生成相应的KieSession //DO5 放入一个存储有状态的KieSession的Map,之后可以在需要的时候先从Map里面找。 }
ksession.insert( message );
public FactHandle insert(final Object object) { return insert( object, /* Not-Dynamic */ null,false,false,null,null ); }
public FactHandle insert(final Object object,final Object tmsValue,final boolean dynamic,boolean logical,final RuleImpl rule,final Activation activation) { checkAlive(); return this.defaultEntryPoint.insert( object, tmsValue,dynamic,logical,rule,activation ); }
在向KieSession插入fact,规则引擎首先检查的是KieSession是否还能使用。
相关文章推荐
- Drools学习 搭建helloworld 与规则文件结构
- drools之helloworld
- SymbianOS Series 60学习笔记一: HelloWorld之晕
- 学习J2ME第一阶段总结:helloworld
- 网页设计需要学习哪些技术
- ASP.NET控件开发学习笔记--第一回 HelloWorld
- 求助:学习 -- C++ -- VC++,windows编程各阶段需要看哪些书
- .net初学必读(一)学习.net技术后能做哪些开发
- 驱动学习笔记(一)HelloWorld
- 关于ant的build的学习 hibernate中的一个例子 HelloWorld的
- 大学生应该学习哪些电子知识
- JBoss Rules 学习笔记(六)—— Drools规则语言详解(上)
- JBoss Rules 学习(四): Drools规则引擎 (下)
- 大学生应该学习哪些电子知识(来自老古网)
- Linux C编程学习日志——第一课 HelloWorld
- 我的Java学习路三:经典HelloWorld
- 大学生应该学习哪些电子知识(转)
- JBoss Rules 学习笔记(三)——DRools规则引擎(上)
- Struts 2 学习笔记 - HelloWorld
- 大学生应该学习哪些电子知识