Drools7.x 学习二-基础理解

一、无国界知识会议

1.术语

无状态会话:不利用推理,形成最简单的用例。无状态会话可以被调用,就像一个函数一样传递一些数据然后接收一些结果。

常见示例

  • 验证:
    这个人有资格获得抵押贷款吗?
  • 计算:
    计算抵押贷款保费。
  • 路由和过滤:
    将传入的消息(如电子邮件)过滤到文件夹中。
    将传入的消息发送到目的地。

2.引入

驾照申请的例子
规则:取消任何年龄小于18 岁的申请人的资格
drools规则编码:

package com.company.license
rule "Is of valid age"
	when $a : Applicant( age < 18 )
	then $a.setValid( false );
end
2.1 规则内容解析
  • 当将数据实例插入引擎时,它将根据规则的约束进行评估,
  • 在这种情况下,对一个规则只有两个约束。
    • 申请人类型是第一个对象类型约束,并且age < 18是第二个字段约束。
    • 对象类型约束加上其零个或多个字段约束称为模式
    • 当插入的实例满足对象类型约束和所有字段约束时, 它被称为匹配。
  • $a是一个绑定变量,它允许我们在结果中引用匹配的对象。它的属性可以更新。美元字符是可选的,但它有助于区分变量名称和字段名称。"a"是变量名称,可以随便命名。
  • 将模式与插入的数据匹配的过程通常被称为模式匹配
2.2 规则使用
  • 要使用此规则,必须将其设置为Drools文件,只是带有.drl扩展名的纯文本文件(“Drools Rule Language’的缩写)。
  • 规则存储在Kie项目中。Kie项目具有普通Maven项目的结构,其中包含一个定义可以创建的KieBases和KieSessions的附加文件(kmodule.xml) 。
  • kmodule.xml文件必须放在Maven项目的resources/META-INF文件夹中,而
  • 所有Drools规则文件,必须存储在resources文件夹或其下的任何其他子文件夹中。
2.3 代码解读
    @Test
    public void test01() {
        KieServices ks = KieServices.Factory.get();
        KieContainer kc = ks.getKieClasspathContainer();
        StatelessKieSession ksession = kc.newStatelessKieSession();
        Applicant a = new Applicant("Xiao,ming", 15, true);
        assertTrue( a.valid );
        ksession.execute( a );
        assertFalse( a.valid);
    }

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

  • 上面的代码片段编译了在类路径中找到的所有DRL文件,并将此编译的结果
    a KieModule放在KieContainer。如果没有错误,我们现在可以从中创建会话
    KieContainer并执行一些数据。

二、有国界知识会议

1.术语

有状态会话:有状态会话是长期存在的,并允许随着时间的推移进行迭代更改。
常见示例
监控.
半自动购买的股市监测和分析。
诊断
故障查找,医疗诊断
后勤
包裹跟踪和交付配置
合规
验证市场交易的合法性。

与无状态会话相比,dispose()之后必须调用该方法以确保没有内存泄漏,因为
KieBase在创建状态知识会话时包含对有状态知识会话的引用。
由于有状态知识会话是最常用的会话类型,因此它仅KieSession在KIE API中命名。
KieSession 也支持BatchExecutor接口,例如StatelessKieSession。
唯一的区别是FireAllRules命令不会在有状态会话结束时自动调用。

2.引入

我们以监控用例为例说明了发出火警的示例。仅使用四个班级,我们代表-一个房
子里的房间,每个房间都有一一个洒水车。如果在房间内发生火灾,我们用单个Fire
实例表示。

实体类

public class Room {
	private String name
	// getter and setter methods here
}
public class Sprinkler { 
	private Room room;
	private boolean on;
	// getter and setter methods here
}

public class Fire {
	private Room room;
	// getter and setter methods here
}
public class Alarm { }

规则编码

rule "When there is a fire turn on the sprinkler"
when
   Fire($room : room)
   $sprinkler : Sprinkler( room == $room, on == false )
then
   modify( $sprinkler ) { setOn( true ) };
   System. out.println("Turn on the sprinkler for room " +$room. getName());
end


rule "When the fire is gone turn off the sprinkler"
when
   $room : Room( )
   $sprinkler : Sprinkler( room == $room, on == true )
   not Fire( room == $room )
then
   modify( $sprinkler ) { setOn( false ) };
   System.out.println( "Turn off the sprinkler for room " +$room.getName() );
end

rule "Raise the alarm when we have one or more fires "
when
   exists Fire()
then
   insert( new Alarm() ) ;
   System. out.println( "Raise the alarm" ) ;
end


rule "Cancel the alarm when all the fires have gone"
when
   not Fire()
   $alarm : Alarm( )
then
   delete( $alarm ) ;
   System.out.println( "Cancel the alarm");
end

rule "Status output when things are ok"
when
   not Alarm()
   Sprinkler( on == false )
then
   System.out.println( "Everything is ok" );
end

rule "Show Sprinklers"
when
   $room : Room()
   $sprinkler : Sprinkler(room == $room )
then
   System. out.println( "room:"+$room.getName()+"sprinkler:" +$sprinkler.getRoom().getName() ) ;
end

执行编码

    @Test
    public void test04() {

        KieServices kieServices = KieServices.Factory.get();
        KieContainer kContainer = kieServices.getKieClasspathContainer();
        KieSession ksession = kContainer.newKieSession();

        //随着会话的创建,现在可以随着时间的推移迭代地使用它。Room创建并插入四个
        //对象,以及Sprinkler每个房间的一个对象。此时引擎已完成所有匹配,但尚未
        //启动任何规则。调用ksession. fireAllRules()允许匹配的规则触发,但没有火将
        //产生健康消息。
        String[] names = new String[]{"kitchen", "bedroom", "office",
                "livingroom"};
        Map<String, Room> name2room = new HashMap<String, Room>();
        for (String name : names) {
            Room room = new Room(name);
            name2room.put(name, room);
            ksession.insert(room);
            Sprinkler sprinkler = new Sprinkler(room);
            ksession.insert(sprinkler);
        }
        ksession.fireAllRules();

        //我们现在制􏲌两个火焰并插入它们这次次保留了􏲍返回的对象FactHandle。
        //事实句柄是插入实例的内􏰇引擎引用,允􏱓在稍后的时􏱡点撤消或修改实例。
        // 现在发动机发生火灾,一旦fireAllRules()呼叫,􏱵警报就会升􏲎起,
        // 相应的洒水喷头也会打开。
        Fire kitchenFire = new Fire(name2room.get("kitchen") );
        Fire officeFire = new Fire(name2room.get("office") );
        FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
        FactHandle officeFireHandle = ksession.insert( officeFire );
        ksession.fireAllRules();

        //一段时间后,火灾将被扑灭,Fire实例将被收回。
        //这导致洒水器关闭,警报被取消,最终再次打印健康信息。
        ksession. delete( kitchenFireHandle ) ;
        ksession. delete( officeFireHandle );
        ksession.fireAllRules();

        ksession.dispose();
    }

三、方法与规则

人们常常混淆方法和规则,而新规则用户经常会问:“我如何称呼规则?”

public void helloWorld (Person person) {
  if ( person. getName() .equals( "Chuck" ) ) {
  	System. out. println( "Hello Chuck" );
  }
}

● 方法直接调用。
● 通过特定实例。
● 一次调用导致单次执行。

rule "Hello World" 
	when
		Person( name == "Chuck" )
	then
		System . out. println( "Hello Chuck" ) ;
end

● 只要将规则插入引擎,规则就可以通过匹配任何数据来执行。
● 永远不能直接调用规则。
● 无法将特定实例传递给规则。
● 根据匹配,规则可能会触发一次或多次, 或者根本不会触发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值