IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 5 Drools高级属性(global全局变量、query查询、function函数,halt) -> 正文阅读

[开发测试]5 Drools高级属性(global全局变量、query查询、function函数,halt)

5 Drools高级属性

? 这部分,我们来学习一下Drools中的一些高级属性的使用。

5.1 global全局变量

? global关键字可以用来在规则文件中定义全局变量,它可以让应用程序中的对象在规则文件中都能够被访问。可以用来为规则文件提供数据或服务,从而贯穿整个规则文件的执行过程。该关键字的使用方式在下面的例子中会做介绍,我们编写一个规则文件,文件名为globalDemo.drl,具体代码如下:

package rules;
import com.dream21th.first.utils.CommonUtils;
import java.util.List;
import java.util.ArrayList;
import com.dream21th.first.GlobalDTO;

global java.lang.Integer num;   //此处定义一个全局计算数
global CommonUtils utils;       //这里定义了一个普通的javaBean
global List<String> list;       //这里定义了一个简单的List数组


rule "global_demo_1"
    when
       GlobalDTO()
    then
       num++; //计算只在当前规则中有效
       System.out.println(utils.whoAmI());
       list.add("这是规则global_demo_1");
       System.out.println("这是规则global_demo_1的num:"+num);
end

rule "global_demo_2"
    when
       GlobalDTO()
    then
       num++; //计算只在当前规则中有效
       list.add("这是规则global_demo_2");
       System.out.println("这是规则global_demo_2的num:"+num);
end


rule "global_demo_3"
    when
       GlobalDTO()
    then
       System.out.println("num:"+num);
       System.out.println("list:"+list);
end

? 编写测试案例如下:

    @Test
    public void testGlobal(){
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieClasspathContainer =kieServices.getKieClasspathContainer();
        //会话对象,用于和规则引擎交互
        KieSession kieSession = kieClasspathContainer.newKieSession();

        //设置全局变量,名称和类型必须和规则文件中定义的全局变量名称对应
        kieSession.setGlobal("utils",new CommonUtils());
        Integer num=100;
        kieSession.setGlobal("num",num);
        List<String> list = new ArrayList();
        kieSession.setGlobal("list",list);
        kieSession.insert(new GlobalDTO());

        //激活规则引擎,如果规则匹配成功则执行规则
        kieSession.fireAllRules();

        System.out.println("这是外面num:"+num+"  这是外面的list:"+list);
        //关闭会话
        kieSession.dispose();
    }

? 其他在本例子使用到的类:

package com.dream21th.first.utils;

/*
 * @Author dream21th
 **/
public class CommonUtils {

    public String whoAmI(){
        return "unkonw";
    }
}
package com.dream21th.first;

/*
 * 仅作为测试使用
 * @Author dream21th
 **/
public class GlobalDTO {
}

案例解析:

? 1,本例子中,我们定义了三个global属性的变量,普通的Integer类型的num,自定义的javabean类型的CommonUtils,以及一个简单的List集合类型;

? 2,我们在测试过程中给num的初始值为100,集合list初始为一个空的;

? 3,在规则里面分别对num进行了递增加1,向list中加入了一条数据,这里需要注意对基本类型的修改只限于当前规则,不会外溢到其他规则。

运行测试案例,控制台输出:

unkonw
这是规则global_demo_1的num:101
这是规则global_demo_2的num:101
num:100
list:[这是规则global_demo_1, 这是规则global_demo_2]
这是外面num:100  这是外面的list:[这是规则global_demo_1, 这是规则global_demo_2]

5.2 query查询

? query属性提供了一种查询working memory中符合约束条件的Fact对象的方法。如果我们想知道工作内存中有哪些满足条件的对象,我们就可以通过query关键字属性来实现,具体的使用格式如下:

query 查询的名称(可选参数)
    LHS
end

? 接着我们编写如下的查询逻辑:

package rules;
import com.dream21th.first.PersonBasicInfo;

//不带参数的查询
//当前query用于查询Working Memory中age>10的PersonBasicInfo对象
query "query_1"
    $personBasicInfo:PersonBasicInfo(age > 10)
end

//带有参数的查询
//当前query用于查询Working Memory中age>10同时name需要和传递的参数name相同的PersonBasicInfo对象
query "query_2"(String nm)
    $personBasicInfo:PersonBasicInfo(age > 20 && name == nm)
end

? 编写测试用例代码:

    @Test
    public void testQuery() {
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieClasspathContainer.newKieSession();

        PersonBasicInfo personBasicInfo1 = new PersonBasicInfo();
        personBasicInfo1.setName("张三");
        personBasicInfo1.setMonthIn(BigDecimal.ONE);
        personBasicInfo1.setAge(23);

        PersonBasicInfo personBasicInfo2 = new PersonBasicInfo();
        personBasicInfo2.setName("赵鹏");
        personBasicInfo2.setMonthIn(BigDecimal.ONE);
        personBasicInfo2.setAge(8);

        PersonBasicInfo personBasicInfo3 = new PersonBasicInfo();
        personBasicInfo3.setName("李明文");
        personBasicInfo3.setMonthIn(BigDecimal.ONE);
        personBasicInfo3.setAge(22);

       //将对象插入Working Memory中
        kieSession.insert(personBasicInfo1);
        kieSession.insert(personBasicInfo2);
        kieSession.insert(personBasicInfo3);

        //调用规则文件中的查询
        QueryResults results1 = kieSession.getQueryResults("query_1");
        int size = results1.size();
        System.out.println("size=" + size);
        for (QueryResultsRow row : results1) {
            PersonBasicInfo personBasicInfo = (PersonBasicInfo) row.get("$personBasicInfo");
            System.out.println(personBasicInfo);
        }

         //调用规则文件中的查询
        QueryResults results2 = kieSession.getQueryResults("query_2", "李明文");
        size = results2.size();
        System.out.println("size=" + size);
        for (QueryResultsRow row : results2) {
            PersonBasicInfo personBasicInfo = (PersonBasicInfo) row.get("$personBasicInfo");
            System.out.println(personBasicInfo);
        }
        //kieSession.fireAllRules();
        kieSession.dispose();
    }

案例说明:

? 1,在这个案例中我们编写了两个查询逻辑,一个方法不带参数,另外一个带有一个参数;

? 2,在测试代码中,我们向工作内存中插入三个对象,并查询,运行结果满足预期。

5.3 function函数

? function关键字用于在规则文件中定义函数,和java类中的方法一样,如果有一部分代码比较长或者多处有使用,我们就可以抽象出函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。

? 函数定义的语法结构如下:

function 返回值类型 函数名(可选参数){
    //逻辑代码
}

? 我们接下来编写规则functionDemo.drl,规则文件的具体内容如下:

package rules;
import com.dream21th.first.PersonBasicInfo;

function String doSomething(String something){
    return "do  "+something;
}

rule "function_1"
    when
      $p:PersonBasicInfo(name=='functionTest')
    then
       System.out.println(doSomething("sleep"));
end

? 编写测试案例:

    @Test
    public void testFunction(){
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieClasspathContainer =kieServices.getKieClasspathContainer();
        //会话对象,用于和规则引擎交互
        KieSession kieSession = kieClasspathContainer.newKieSession();

        PersonBasicInfo personBasicInfo=new PersonBasicInfo();
        personBasicInfo.setName("functionTest");
        personBasicInfo.setMonthIn(BigDecimal.ONE);
        kieSession.insert(personBasicInfo);

        //激活规则引擎,如果规则匹配成功则执行规则
        kieSession.fireAllRules();

        //关闭会话
        kieSession.dispose();
    }

案例说明:

? 1,编写一个规则,规则中有一个名为doSomething的函数,这个函数没有做很多事情,只是将入参前面加了一个do返回出去;

? 2,规则的触发条件是工作内存中有一个PersonBasicInfo的对象,并且name属性的值为functionTest就会触发,触发后发现调用了写的函数。

5.4 其他一些属性介绍

? 除了上面介绍的一些比较常用的属性外,还有一些属性在实际的开发过程中也会经常使用,下面就来简单介绍一下这些属性及使用方法。

5.4.1 in/not in

? 从名字就可以大概猜到这两个属性的使用场景,这两个属性主要是用来判断一个字符串或者数字在不在一个集合里面。

package rules;
import com.dream21th.first.PersonBasicInfo;

rule "in_demo"
    when
      $p:PersonBasicInfo(name in ("马超","黄忠","程普")) 
    then
      System.out.println("触发in_demo");
end

rule "not_in_demo"
    when
      $p:PersonBasicInfo(name not in ("马超","黄忠","程普"))
    then
      System.out.println("触发not_in_demo");
end

案例说明:第一个规则说的是name属性在"马超",“黄忠”,"程普"三个中才触发;第二个规则说不在这三个属性中才触发。

5.4.2 not

? not用于判断Working Memory中是否存在某个Fact对象,如果不存在则返回true,如果存在则返回false。我们用下面的例子来看一下这个属性的使用

rule "not_1"
    when
      not PersonBasicInfo()
    then
      System.out.println("工作内存中没有PersonBasicInfo对象");
end

rule "not_2"
    when
      not PersonBasicInfo(name=='张飞')
    then
      System.out.println("工作内存中没有name属性为张飞的PersonBasicInfo对象");
end

5.4.3 条件元素exists

? exists的作用与not相反,用于判断工作内存中是否存在某个Fact对象,如果存在则返回true,不存在则返回false。接下来可能有人会有疑问,我们前面在LHS部分进行条件编写时并没有使用exists也可以达到判断Working Memory中是否存在某个符合条件的Fact元素的目的,那么我们使用exists还有什么意义?其实两者的区别在于:当向Working Memory中加入多个满足条件的Fact对象时,使用了exists的规则只执行一次,不使用exists的规则会执行多次。

? 接下来我们通过下面的例子来看看这个属性的使用:

package rules;
import com.dream21th.first.PersonBasicInfo;

rule "exist_1"
    when
       exists PersonBasicInfo(name=='潘飞')
    then
       System.out.println("触发exist_1");
end

rule "no_exist_2"
    when
       PersonBasicInfo(name=='潘飞')
    then
       System.out.println("触发exist_2");
end

? 测试案例:

    @Test
    public void testExists(){
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieClasspathContainer =kieServices.getKieClasspathContainer();
        //会话对象,用于和规则引擎交互
        KieSession kieSession = kieClasspathContainer.newKieSession();

        PersonBasicInfo personBasicInfo=new PersonBasicInfo();
        personBasicInfo.setName("潘飞");
        personBasicInfo.setMonthIn(BigDecimal.ONE);
        PersonBasicInfo personBasicInfo1=new PersonBasicInfo();
        personBasicInfo1.setName("潘飞");
        personBasicInfo1.setMonthIn(BigDecimal.ONE);
        kieSession.insert(personBasicInfo);
        kieSession.insert(personBasicInfo1);

        //激活规则引擎,如果规则匹配成功则执行规则
        kieSession.fireAllRules();

        //关闭会话
        kieSession.dispose();
    }

案例说明:

? 1,向工作内存中插入两个PersonBasicInfo对象,发现带有属性exists的规则只触发一次,不带的执行了2次。

5.4.4 规则继承

? 在编写Drools规则的时候我们可以使用extend来继承另外一个规则,类型java语言中的继承。

rule "rule_1"
    when
        PersonBasicInfo(age > 10)
    then
        System.out.println("规则:rule_1触发");
end

rule "rule_2" extends "rule_1" //继承上面的规则
    when
        /*
        **此处的条件虽然只写了一个,但是从上面的规则继承了一个条件,所以当前规则存在两个条件
        ,即PersonBasicInfo(age < 20)和PersonBasicInfo(age > 10)
        */
        PersonBasicInfo(age < 20) 
    then
        System.out.println("规则:rule_2触发");
end

5.4.5 halt

? halt方法的作用是立即终止后面所有规则的执行。

package testhalt
rule "rule_halt_1"
    when
    then
        System.out.println("规则:rule_halt_1触发");
        drools.halt();//立即终止后面所有规则执行
end

//当前规则并不会触发,因为上面的规则调用了halt方法导致后面所有规则都不会执行
rule "rule_halt_2"
    when
    then
        System.out.println("规则:rule_halt_2触发");
end

5.4.6 getWorkingMemory

? getWorkingMemory方法的作用是返回工作内存对象。

rule "rule_getWorkingMemory"
    when
    then
        System.out.println(drools.getWorkingMemory());
end

5.4.7 getRule

? getRule方法的作用是返回规则对象(当前规则)。

rule "rule_getRule"
    when
    then
        System.out.println(drools.getRule());
end
//运行结果
[Rule name=rule_getRule, agendaGroup=MAIN, salience=0, no-loop=false]
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:56:38  更:2022-03-15 22:56:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:11:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码