1.RuleSession到底是干什么的?怎么用?
答:RuleSession(包含了StatelessRuleSession和StatefulRuleSession),rulesession字面上理解是一个规则会话,既然是会话,那么他肯定会包含会话双方的信息,那么会话的双方是谁呢?很简单,我们来看看他的构造器,这里也揭示了一个分析类的最好的方法,那就是一个类构建后应该需要的最少信息,所以看构造器是最直接的,大家知道rulesession是一个抽象类,我们研究他的实现类 StatelessRuleSessionImpl,他的构造器含有三个参数:
String bindUri-RuleExecutionSet所绑定的URI,也就是说通过这个URI可以找到我们的规则集!比如我们有个足球程序,那么我们可能就会为足球规则集取个名字叫做“FootBall-bindUri”。
Map properties-为了建立rulesession所需的额外的属性,其实这是jsr为了扩展的需要规定要传这个参数,在drool中并没有使用这个属性做任何事情!
RuleExecutionSetRepository repository-规则仓库,这个仓库的具体实现可以是文件目录或者是数据库,看你自己的具体情况,这个仓库将会根据上面的URI参数找到需要执行的规则集,找不到就报一个找不到的异常,找到了就把这个规则集设为本类的一个属性。
2.这个rulesession由谁建立?谁触发建立他的?
答:这个session会由用户建立的,客户端代码来创建,好比浏览器端的用户与服务器端建立一个请求会话,客户端程序创建会话,他把要用的规则集和针对这个规则集的事实列表list传过来,拿足球为例,这个rulesession就含有一本足球规则手册+某球员一系列的犯规记录,用户同时还应传入一个 objectFilter,这个filter告诉ruleseeion如何过滤结果集,最终rulesession开始执行,针对犯规记录逐个查询规则手册,最后会把判罚结果返回给用户!
rulesession执行的时候是调用executeRules方法,在这个方法中,首先创建了一个WorkingMemory对象,这个很好理解,你要开工干活,肯定需要一个工作台的,那么这个工作台上面放上规则法律典籍(RuleExecutionSet)和案件卷宗(fact list),还有其他一些辅助的工具数据之类的,好了工作台摆好了,可以开工了!
3.WorkingMemory的工作原理?也就是说我们让他如何作满足我们的要求,返回我们需要的结果?
答:在rulesession的executerules方法中会不断的迭代那些传进来的事实,然后交给workingmemory,好比我先拿起一条犯罪记录,然后调用WorkingMemory.assertObject(yourFactObject) 。然后我就会检查是否匹配规则,也就是说查法律条文是否犯罪,比如有的人虐待动物,虽然不对,但是法律不认为他有罪,我就不能执行他,如果assert完所有的规则,我就马上开始workingMemory.fireAllRules();调用所有匹配上了的规则开始执行!
4.WorkingMemory的assertObject(yourFactObject)验证事实匹配规则的具体过程?
答:你的事实对象传入后首先会看看是否评估过,因为每次评估一个事实都会把当前事实对象加入workingmemory的map中,也就是说会做个记号,以事实对象作为map的key。这样一个事实进来,首先以他为key到map中查询,返回一个FactHandle对象!这个 FactHandle 是一个代表在 Working Memory 中你的 asserted Object 的令牌( token )。
当你希望 retract 或者 modify 一个对象的时候,这个令牌让你用来同 WorkingMemory 进行交互。
Cheese stilton = new Cheese( " stilton " );
FactHandle stiltonHandle = workingMemory.assertObject( stilton );
WorkingMeomry 有两种 assertion 模式: Equality 和 Identity (默认是 Identity )。
Identity 模式下 WorkingMemory 使用一个 IdentityHashMap 来存储所有的 asserted Objects 。这个模式下,当 asserted 的 Object 是同一个实例时,它返回同一个 FactHandle 。
Equality 模式下 WorkingMemory 使用一个 HashMap 来存储所有的 asserted Objects 。这个模式下,当 asserted 的 Object 相等时,它返回同一个 FactHandle 。
( WorkingMemory.assertObject(yourObjcet) 只是进行 assertion 的一种 regular 方法,还存在有一种称为 logical assertion 的动作)。
5.WorkingMemory中有个public的retractObject方法,他是用来干什么的?
答:Retraction
基本上就是 assert 的逆操作。当你 retract 一个 fact , WorkingMemory 将不再跟踪那个 fact 。任何被 activated 并依赖那个 fact 的规则将被取消。注意:完全有可能存在某条规则是依赖于一个 fact 的“不存在”( non existence )。在这种情况下, retract 一个 fact 将导致一条规则被激活。对一个 Fact 进行 Retraction ,必须用 assert 时返回的那个 FactHandle 做为参数。
Cheese stilton = new Cheese( " stilton " );
FactHandle stiltonHandle = workingMemory.assertObject( stilton );
...
workingMemory.retractObject( stiltonHandle );
6.WorkingMemory中有个public的modifyObject方法,他是用来干什么的?
答:Modification
当一个 Fact 被修改了,会通知规则引擎进行重新处理。在规则引擎内部实际上是对旧的 Fact 进行 retract ,然后对新的 Object 再进行 assert 。要使用 modifyObject() 方法来通知 Working Memory ,被改变的 Object 并不会自己通知规则引擎。注意: modifyObject() 方法总是要把被修改的 Object 做为第二参数,这就允许你把一个不可变对象替换为另一个新对象。
Cheese stilton = new Cheese( " stilton " );
FactHandle stiltonHandle = workingMemory.assertObject( stilton );
...
stilton.setPrice( 100 );
workingMemory.modifyObject( stiltonHandle, stilton );
7.WorkingMemory中含有Listener的一些操作方法,他们具体干什么用的?如何用?
答: Property Change Listener
如果你的 fact 对象是 JavaBean ,你可以为它们实现一个 property change listener ,然后把它告诉规则引擎。这意味着,当一个 fact 改变时,规则引擎将会自动知道,并进行响应的动作(你不需要调用 modifyObject() 方法来通知 WorkingMemory )。 Proxy libraries 将会帮助实现这一切。要让 Property Change Listener 生效,还要将 fact 设置为动态( dynamic )模式,通过将 true 做为 assertObject() 方法的第二个参数来实现:
Cheese stilton = new Cheese( " stilton " );
FactHandle stiltonHandle = workingMemory.assertObject( stilton, true ); // specifies t hat this is a dynamic fact
然后要在 JavaBean 中加入一个 PropertyChangeSupport 实例,和两个方法: addPropertyChangeListener() 和 removePropertyChangeListener() 。最后要在 JavaBean 的 setter 方法中通知 PropertyChangeSupport 所发生的变化。示例代码如下:
private final PropertyChangeSupport changes = new PropertyChangeSupport( this );
public void addPropertyChangeListener( final PropertyChangeListener l) {
this .changes.addPropertyChangeListener( l );
}
public void removePropertyChangeListener( final PropertyChangeListener l) {
this .changes.removePropertyChangeListener( l );
}
public void setState( final String newState) {
String oldState = this .state;
this .state = newState;
this .changes.firePropertyChange( " state " , oldState, newState );