Java规则引擎Drools急速入门

news2024/11/20 16:32:25

文章目录

        • 1.Drools规则引擎简介
        • 2.Drools API开发步骤
        • 3.SpringBoot整合Drools案例
        • 4.Drools基础语法
        • 5.Drools条件语法部分
        • 6.Drools结果操作部分
        • 7.Drools内置属性部分
        • 8.Drools高级语法部分

1.Drools规则引擎简介

(1)什么是规则引擎

​ 全称为业务规则管理系统,英⽂名为BRMS(即 Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。 需要注意的是规则引擎并不是一个具体的技术框架,而是指的⼀类系统,即业务规则管理系统。

​ 目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等,使用最为广泛并且开源的是Drools。

​ 规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出的平台。

(2)规则引擎主要的应用场景

  • 风险控制系统----风险贷款、风险评估
  • 反欺诈项目----银行贷款、征信验证
  • 决策平台系统----财务计算
  • 促销平台系统----满减、打折、加价购

(3)Drools介绍

​ Drools是⼀款由JBoss组织提供的基于Java语⾔开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在⽂件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、不⽤重启服务器就可以在线上环境立即生效。

在这里插入图片描述

​ Drools官网地址:https://drools.org/

​ drools源码下载地址:https://github.com/kiegroup/drools

(4)使用规则引擎能解决什么问题

  • 硬编码实现业务规则难以维护
  • 硬编码实现业务规则难以应对变化
  • 业务规则发⽣变化需要修改代码,重启服务后才能生效

(5)使用规则引擎的优势

  • 业务规则与系统代码分离,实现业务规则的集中管理
  • 在不重启服务的情况下可随时对业务规则进行扩展和维护
  • 可以动态修改业务规则,从⽽快速响应需求变更
  • 规则引擎是相对独立的,只关心业务规则,使得业务分析⼈员也可以参与编辑、维护系统的业务规则
  • 减少了硬编码业务规则的成本和风险
  • 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单

2.Drools API开发步骤

在这里插入图片描述

我们在操作Drools时经常使用的API以及它们之间的关系如下图:

在这里插入图片描述

Kie全称为Knowledge Is Everything,即“知识就是一切”的缩写,是Jboss一系列项目的总称。

规则引擎构成

drools规则引擎由以下三部分组成:

  • Working Memory(工作内存)
  • Rule Base(规则库)
  • Inference Engine(推理引擎)

其中Inference Engine(推理引擎)又包括:

● Pattern Matcher(匹配器) 具体匹配哪⼀个规则,由这个完成

● Agenda(议程)

● Execution Engine(执行引擎)

在这里插入图片描述

相关概念说明

  • **Working Memory:**工作内存,drools规则引擎会从Working Memory中获取数据和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要我们的数据插入到Working Memory中即可。

  • **Fact:**事实,是指在drools规则应用中,将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象。

  • **Rule Base:**规则库,我们在规则文件中定义的规则都会被加载到规则库中。

  • **Pattern Matcher:**匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。

  • **Agenda:**议程,用于存放通过匹配器进行模式匹配后被激活的规则。

  • **Execution Engine:**执行引擎,执行Agenda中被激活的规则。

规则引擎执行过程

在这里插入图片描述

3.SpringBoot整合Drools案例

(1)案例背景

某电商平台的促销活动,活动规则是根据⽤户购买订单的⾦额给⽤户送相应的积分,购买的越多送的积分越多

用户购买的金额和对应送多少积分的规则如下:

100元以下, 不加分

100元-500元 加100分

500元-1000元 加500分

1000元 以上 加1000分

按照常理,作为一个工作一两年的开发工程师来说,这不是分分钟搞定的事情,直接上午开发,下午提测。

/**
 * 设置订单积分
 */
public void setOrderPoint(Order order){
    if (order.getAmout() <= 100){
    	order.setScore(0);
    }else if(order.getAmout() > 100 && order.getAmout() <= 500){
    	order.setScore(100);
    }else if(order.getAmout() > 500 && order.getAmout() <= 1000){
    	order.setScore(500);
    }else{
    	order.setScore(1000);
    }
}

但是,假如说现在产品经理不想100元以下不送积分了,想要200元以下不送金额了,是不是又要重新改代码了。所以Drools帮我们解决在不改动原有代码的情况下修改规则的信息。

(2)创建Maven项目,加入SpringBoot依赖

在这里插入图片描述

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.5.12</version>
            <relativePath/>
        </parent>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

(3)resources下创建yml配置文件

server:
  port: 8888

spring:
  application:
    name: drools-server

(4)创建SpringBoot启动主类

@SpringBootApplication
public class DroolsApplication {
    public static void main(String[] objArgs)
    {
        SpringApplication.run(DroolsApplication.class, objArgs);
    }
}

(5)添加单元测试依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

(6)添加Drools和lombok依赖

        <!--drools规则引擎-->
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>7.6.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>7.6.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-templates</artifactId>
            <version>7.6.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-api</artifactId>
            <version>7.6.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>7.6.0.Final</version>
        </dependency>
        <!--添加lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>compile</scope>
        </dependency>

(7)创建订单实体类Order

/**
 * @description 订单实体类
 * @author lixiang
 */
@Data
public class Order {

    /**
     * 订单金额
     */
    private int amount;

    /**
     * 积分
     */
    private int score;
}

(8)创建规则⽂件/resources/rules/score-rules.drl

package rules

import com.lixiang.domain.Order

//规则1:100元以下, 不加积分
rule "score_1"
when
    $s : Order(amount <= 100)
then
    $s.setScore(0);
    System.out.println("消费100元以下, 不加积分 ");
end

//规则2:100元-500元 加100积分
rule "score_2"
when
    $s : Order(amount > 100 && amount <= 500)
then
    $s.setScore(100);
    System.out.println("消费100元-500元 加100积分 ");
end

//规则3:500元-1000元 加500积分
rule "score_3"
when
    $s : Order(amount > 500 && amount <= 1000)
then
    $s.setScore(500);
    System.out.println("消费500元-1000元 加500积分 ");
end

//规则4:1000元 以上 加1000积分
rule "score_4"
when
    $s : Order(amount > 1000)
then
    $s.setScore(1000);
    System.out.println("消费1000元 以上 加1000积分 ");
end

(9)创建DroolsConfig配置类


/**
 * @author lixiang
 * @description Drools规则引擎配置类
 */
@Configuration
public class DroolsConfig {

    /**
     * 定义规则路径
     */
    private static final String RULES_PATH = "rules/";

    private final KieServices kieServices = KieServices.Factory.get();

    /**
     * 获取规则文件
     * @return
     * @throws IOException
     */
    @Bean
    @ConditionalOnMissingBean
    public KieFileSystem kieFileSystem() throws IOException {
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        ResourcePatternResolver resourcePatternResolver =  new PathMatchingResourcePatternResolver();
        Resource[] files = resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");
        String path;
        for (Resource file : files) {
            path = RULES_PATH + file.getFilename();
            kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));
        }
        return kieFileSystem;
    }

    /**
     * 创建Kie容器
     * @return
     * @throws IOException
     */
    @Bean
    @ConditionalOnMissingBean
    public KieContainer kieContainer() throws IOException {
        KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
        kieBuilder.buildAll();
        return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
    }

    @Bean
    @ConditionalOnMissingBean
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }

    @Bean
    @ConditionalOnMissingBean
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }
}

(10)编写测试类

@SpringBootTest
public class DroolsTest {

    @Autowired
    private KieBase kieBase;

    @Test
    public void droolsTest(){
        Order order = new Order();
        order.setAmount(200);
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
        System.out.println("订单金额:"+order.getAmount()+",订单积分:"+order.getScore());
    }

}

在这里插入图片描述

4.Drools基础语法

(1)规则文件的构成

drl是Drools Rule Language的缩写。在规则⽂件中编写具体的规则内容。

⼀套完整的规则文件内容构成如下:

  • package:包名,package对应的不⼀定是真正的目录,可以任意写com.abc,同⼀个包下的drl文件可以相互访问
  • import:用于导入类或者静态方法
  • global:全局变量
  • function:自定义函数
  • query:查询
  • rule end:规则体

(2)规则体语法构成

一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)

rule "ruleName" //rule关键字,表示规则开始,参数为规则的唯⼀名称
	attributes //规则属性,是rule与when之间的参数,为可选项
	when //关键字,后⾯是规则的条件部分
		LHS //Left Hand Side,是规则的条件部分
	then //后⾯跟规则的结果部分
		RHS //是规则的结果或⾏为
end //表示⼀个规则的结束

5.Drools条件语法部分

LHS(Left Hand Side):是规则的条件部分的通⽤名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。

(1)约束连接

  • 在 LHS 当中,可以包含 0~n 个条件,多个pattern之间可以采⽤“&&” (and) 、 “||”(or)和“,”(and)来实现,也可以不写,默认连接为and。
rule "rule1"
    when
    	$s : Order(amout > 100 && amout <= 500)
    then
    	$s.setScore(100);
    	System.out.println("成功匹配到规则:100元-500元 加100积分 ");
end
  • 测试代码
    @Test
    public void test1(){
        Order order = new Order();
        order.setAmount(200);
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(2)比较运算符

  • 在 Drools当中共提供了⼗⼆种类型的⽐较操作符, 分别是: >、 >=、 <、 <=、 = =、 !=、contains、 not contains、memberof、not memberof、matches、not matches;在这⼗⼆种类型的比较操作符当中,前六个是⽐较常⻅也是⽤的⽐较多的⽐较操作符。
符号说明
>大于
<小于
>=大于等于
<=小于等于
==等于
!=不等于
contains检查一个Fact对象的某个属性值是否包含一个指定的对象值
not contains检查⼀个Fact对象的某个属性值是否不包含⼀个指定的对象值
memberOf判断⼀个Fact对象的某个属性是否在⼀个或多个集合中
not memberOf判断⼀个Fact对象的某个属性是否不在⼀个或多个集合中
matches判断⼀个Fact对象的属性是否与提供的标准的Java正则表达式进⾏匹配
not matches判断⼀个Fact对象的属性是否不与提供的标准的Java正则表达式进⾏匹配

验证:

  • 创建订单项实体类
/**
 * @description 订单项
 * @author lixiang
 */
@Data
public class OrderItem {

    /**
     * 订单项名称
     */
    private String name;

    /**
     * 订单项金额
     */
    private int amount;
}
  • 订单中加入订单项集合
/**
 * @description 订单实体类
 * @author lixiang
 */
@Data
public class Order {

    /**
     * 订单金额
     */
    private int amount;

    /**
     * 积分
     */
    private int score;

    List<OrderItem> orderItemList;
}
  • 测试contains 规则
规则文件内容:

//测试contains规则
rule "rule1"
    when
        $orderItem:OrderItem();
        $order:Order(orderItemList contains $orderItem);
    then
        System.out.println("测试 contains 规则触发:"+$order.getOrderItemList());
end
	//java测试代码
	@Test
    public void test2(){
        Order order = new Order();
        order.setAmount(200);

        OrderItem orderItem = new OrderItem();
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(orderItem);
        order.setOrderItemList(orderItemList);

        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

  • 测试not contains 规则
规则文件内容:

//测试not contains规则
rule "rule1"
    when
        $orderItem:OrderItem();
        $order:Order(orderItemList contains $orderItem);
    then
        System.out.println("测试not contains 规则触发:"+$order.getOrderItemList());
end
	//java测试代码
	@Test
    public void test3(){
        Order order = new Order();
        order.setAmount(200);

        OrderItem orderItem = new OrderItem();
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(orderItem);

        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

  • 测试matches规则
规则文件内容:

//测试⽐较操作符matches
rule "rule3"
    when
    	OrderItem(name matches "订单*")
    then
    	System.out.println("测试⽐较操作符matches触发...");
end
	//java测试代码
	@Test
    public void test3(){
        OrderItem orderItem = new OrderItem();
        orderItem.setName("订单项1");

        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule3"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

  • 测试not matches规则
规则文件内容:

//测试⽐较操作符not matches
rule "rule4"
    when
    	OrderItem(name not matches "订单1.*")
    then
    	System.out.println("测试⽐较操作符not matches触发...");
end
	//java测试代码
	@Test
    public void test3(){
        OrderItem orderItem = new OrderItem();
        orderItem.setName("订单项1");

        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

  • 测试memberOf规则
规则文件内容:

//测试⽐较操作符memberOf
rule "rule5"
    when
    	Order(orderItemList memberOf list)
    then
    	System.out.println("测试⽐较操作符memberOf触发...");
end
	//java测试代码
	@Test
    public void test4(){
        Order order = new Order();
        OrderItem orderItem = new OrderItem();
        List<OrderItem> orderItemList = new ArrayList<>();
        orderItemList.add(orderItem);
        order.setOrderItemList(orderItemList);
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule5"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

  • 测试not memberOf规则
规则文件内容:

//测试⽐较操作符memberOf
rule "rule6"
    when
        $orderItem:OrderItem();
    	Order($orderItem not memberOf orderItemList);
    then
    	System.out.println("测试⽐较操作符not memberOf触发...");
end
	@Test
    public void test4(){
        Order order = new Order();
        OrderItem orderItem = new OrderItem();
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.insert(order);
        kieSession.insert(orderItem);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule6"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

6.Drools结果操作部分

在Drools当中,在RHS里面,提供了一些对当前Working Memory实现快速操作的宏函数或对象,比如insert/insertLogical、update和retract就可以实现对当前Working Memory中的Fact对象进行新增、删除或者是修改。

(1)insert/insertLogical函数

函数insert的作用与我们在java类当中调用StatefulKnowIedgeSession对象的insert方法的作用相同,都是将一个Fact对象插入到当前的Working Memory当中。

需注意:一旦调用 insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配⼀次, 对于没有设置no-loop 属性为 true 的规则,如果条件满足,不管其之前是否执行过都会在执行,这个特性不仅存在于 insert 宏函数上,后⾯介绍的 update、retract 宏函数同样具有该特性,所以在某些情况下因考虑不周调用 insert、update 或 retract 容易发生死循环。

//Drools提供的内置⽅法insert
rule "rule7"
    when
        eval(true); //默认成⽴
    then
        Order order=new Order();
        order.setAmount(1000);
        insert(order);
        System.out.println("测试Drools提供的内置⽅法insert 触发...,order:"+order);
end
    @Test
    public void test6() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule7"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

insertLogical:insertLogical 作⽤与 insert 类似,它的作用也是将⼀个 Fact 对象插入到当前的 Working Memroy 当中

(2)update函数

update函数意义与其名称⼀样, ⽤来实现对当前Working Memory当中的 Fact进⾏更新,⽤来告诉当前的 Working Memory 该 Fact 对象已经发生了变化。

//Drools提供的内置⽅法update
rule "rule8"
    when
        $order:Order(amount == 100);
    then
        $order.setAmount(1000);
        update($order);
        System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end
	@Test
    public void test8() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配

        Order order = new Order();
        order.setAmount(100);
        kieSession.insert(order);

        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule8"));
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(3)retract

retract用来将Wroking Memory当中某个Fact对象从Working Memory当中删除

rule "rule9"
    when
        $order:Order(amount == 100);
    then
        //retract($order); //先不执行删除
        System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
end

rule "rule10"
    when
        $order:Order();
    then
        System.out.println("order:"+$order);
end
    @Test
    public void test9() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配

        Order order = new Order();
        order.setAmount(100);
        kieSession.insert(order);

        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

rule "rule9"
    when
        $order:Order(amount == 100);
    then
        retract($order); //执行删除
        System.out.println("测试Drools提供的内置⽅法retract 触发...,order:"+$order);
end

rule "rule10"
    when
        $order:Order();
    then
        System.out.println("order:"+$order);
end

测试方法还是上面那个

在这里插入图片描述

7.Drools内置属性部分

Drools中提供的属性

属性名说明
salience指定规则执行优先级
dialect指定规则使用的语言类型,取值为java或者mvel
enabled指定规则是否启用
date-effective指定规则生效时间
date-expires指定规则失效时间
activation-group激活分组,具有相同分组名称的规则只能有一个规则触发
agenda-group议程分组,只有获取焦点的组中的规则才有可能触发
timer定时器,指定规则触发的时间
auto-focus自动获取焦点,一般饥饿和agenda-group一起使用
no-loop防止死循环

(1)salience

salience用来设置规则执行的优先级,salience属性的值是一个数字,数字越大执行优先级越高。默认情况下,规则的salience默认值为0。如果不设置salience属性,规则体的执行顺序为由上到下。

rule "rule1"
    salience 1
    when
        eval(true)
    then
        System.out.println("执行规则1");
end
rule "rule2"
    salience 2
    when
        eval(true)
    then
        System.out.println("执行规则2");
end
   @Test
    public void test10() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(2)no-loop

no-loop是用来控制已经执行过的规则在条件再次满足的时候是否再次执行。no-loop属性是一个布尔型默认情况下规则的no-loop属性的值为false,如果no-loop属性值为true,那么就表示该规则只会被引擎检查一次。

//这是一个死循环修改,永远都会被匹配到修改
rule "rule3"
    when
        $order:Order(amount == 100);
    then
        $order.setAmount(100);
        update($order);
        System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end
    @Test
    public void test10() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        Order order = new Order();
        order.setAmount(100);
        kieSession.insert(order);
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

//这是一个死循环修改,永远都会被匹配到修改
rule "rule3"
    no-loop true  //配置no-loop属性
    when
        $order:Order(amount == 100);
    then
        $order.setAmount(100);
        update($order);
        System.out.println("测试Drools提供的内置⽅法update 触发...,order:"+$order);
end

再次测试

在这里插入图片描述

(3)date-effective

date-effective的作用是来控制规则只有达到指定的时候后才会触发,只有当系统时间大于等于date-effective设置的时间值时,规则才会被执行。

date-effective 的值为⼀个日期型的字符串,默认情况下,date-effective 可接受的日期格式为 “dd-MM-yyyy”。

在实际使用中,如果不想使用这种格式,也可以通过java代码去设置System.setProperty(String key,String value)方法来修饰默认的时间格式。

System.setProperty("drools.dateformat","yyyy-MM-dd");
rule "rule4"
    date-effective "2022-11-30"
    when
        eval(true);
    then
        System.out.println("测试Drools date-effective ");
end
    @Test
    public void test10() {
        //设置时间格式
        System.setProperty("drools.dateformat","yyyy-MM-dd");
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
        //关闭会话
        kieSession.dispose();
    }

(4)date-expires

date-expires的作用正好与date-effective属性恰恰相反,date-expires的作用时用来设置规则的有效期,引擎在执行规则的时候,会检查规则有没有date-expires属性,如果有的话,那么将这个属性与当前系统时间进行比较,如果大于系统时间就执行。

rule "rule5"
    date-expires "2022-11-30"
    when
        eval(true);
    then
        System.out.println("测试Drools date-effective ");
end
    @Test
    public void test10() {
        //设置时间格式
        System.setProperty("drools.dateformat","yyyy-MM-dd");
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule4"));
        //关闭会话
        kieSession.dispose();
    }

(5)enabled

enabled的作用就是定义一个规则是否可用。该属性的值是一个布尔值默认该属性的值为true,表示规则是可用的。设置enabled属性为false时,该规则引擎不会执行。

rule "rule1"
    enabled true
    when
        eval(true)
    then
        System.out.println("执行规则1");
end
rule "rule2"
    enabled false
    when
        eval(true)
    then
        System.out.println("执行规则2");
end
    @Test
    public void test11() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(6)dialect

dialect作用是用来定义规则当中要使用的语言类型,目前支持两种类型的语言,mvel和java,默认情况下,如果没有手工设置的话,默认使用java语言。

(7)activation-group

activation-group的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,在执行规则时,具有相同activation-group属性的规则中只要有一个会被执行,其他规则将不再执行。当然具有相同activation-group属性的规则中哪一个会先执行,可以设置salience属性来实现。

rule "rule1"
    activation-group "test"
    when
        eval(true)
    then
        System.out.println("执行规则1");
end
rule "rule2"
    activation-group "test"
    when
        eval(true)
    then
        System.out.println("执行规则2");
end
	@Test
    public void test11() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(8)agenda-group

agenda-group属性是一个字符串,不过通过这个字符串可以分为若干个AgendaGroup,默认情况下,引擎在调用这些设置了agenda-group属性的规则的时候需要显示的指定某个Agenda Group得到Focus,这样位于该Agenda Group当中的规则才会触发执行,否则将不执行。

rule "rule1"
    agenda-group "001"
    when
        eval(true)
    then
        System.out.println("执行规则1");
end
rule "rule2"
    agenda-group "002"
    when
        eval(true)
    then
        System.out.println("执行规则2");
end
	@Test
    public void test11() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //获取执行焦点
        kieSession.getAgenda().getAgendaGroup("002").setFocus();
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(9)auto-focus

auto-focus的作用是在已经设置了agenda-group的规则上设置该规则是否可以自动独取Focus,如果该属性设置为true,那么在执行引擎时,就不需要设置Focus。

rule "rule1"
    agenda-group "001"
    auto-focus true
    when
        eval(true)
    then
        System.out.println("执行规则1");
end
rule "rule2"
    agenda-group "002"
    when
        eval(true)
    then
        System.out.println("执行规则2");
end
	@Test
    public void test11() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //激活规则引擎,如果匹配成功则执行
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(10)timer

timer属性可以通过定时器的方式指定规则执⾏的时间,使⽤方式有两种

方式一:timer(int ?)

此方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。

方式二:timer(cron)

此方式使用标准的unix cron 表达式的使用来定义规则执行的时间。

rule "rule_timer_1"
    timer (5s 2s) //含义:5秒后触发,然后每隔2秒触发⼀次
    when
    then
        System.out.println("规则rule_timer_1触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end

rule "rule_timer_2"
    timer (cron:0/1 * * * * ?) //含义:每隔1秒触发⼀次
    when
    then
        System.out.println("规则rule_timer_2触发,触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
	@Test
    public void test12() throws InterruptedException {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        //启动规则引擎进行规则匹配,知道调用halt方法才结束引擎
        new Thread(kieSession::fireUntilHalt).start();
        //当前线程睡眠10s
        Thread.sleep(10000L);
        //调用halt
        kieSession.halt();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

8.Drools高级语法部分

关键字描述
package包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用
import用于导入类或者静态方法
global全局变量
function自定义函数
query查询
rule end规则体

(1)global全局变量

全局变量,一般用作执行规则后的结果数据返回或对具体某个服务调用等。在调用规则引擎的集成代码中,获取emailService对象,然后将其设置在工作内存中。

语法结构为:global对象类型 对象名称

import java.lang.String;

global java.lang.String name;

rule "rule6"
    when
        eval(true);
    then
        System.out.println("测试Global--全局order:"+name);
end
	@Test
    public void test14() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.setGlobal("name","李祥");
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

(2)query查询

query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定"when"和"then"部分。Query有一个可选参数集合,每一个参数都可选的类型。如果没有指定类型,则默认为Object类型。引擎会尝试转为需要的类型。对于KieBase来说,query的名字是全局性的,因此不要向同一RuleBase的不同包添加相同名称的query。

使用ksession.getQueryResult(“name”)方法可以获得查询的结果,其中name为query的名称,方法的返回结果一个列表,从中可以获取匹配查询到的对象。

import com.lixiang.domain.Order;

//不带参数的进行查询
query "query-1"
    $order : Order(amount == 100)
end
//带参数的进行查询
query "query-2"(Integer amountParam)
    $order : Order(amount == amountParam)
end
	@Test
    public void test14() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        Order order1 = new Order();
        order1.setAmount(1000);
        Order order2 = new Order();
        order2.setAmount(100);

        //添加到工作空间
        kieSession.insert(order1);
        kieSession.insert(order2);

        kieSession.fireAllRules();

        QueryResults queryResults = kieSession.getQueryResults("query-1");
        System.out.println("无查询参数:result size is "+queryResults.size());
        for (QueryResultsRow queryResult : queryResults) {
             Order order = (Order)queryResult.get("$order");
            System.out.println("查询出来的结果:"+order);
        }

        System.out.println("------------------------------------------");

        QueryResults queryResults1 = kieSession.getQueryResults("query-2",1000);
        System.out.println("有查询参数:result size is "+queryResults1.size());
        for (QueryResultsRow queryResult : queryResults) {
            Order order = (Order)queryResult.get("$order");
            System.out.println("查询出来的结果:"+order);
        }

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

在这里插入图片描述

(3)function函数

在规则中可以通过函数来做一些通用的逻辑,就相当于java类中的方法一样。

//定义函数
function String format(String name){
    return "hello "+name;
}

rule "function_rule"
    when
        eval(true);
    then
        //调⽤上⾯定义的函数
        String ret = format("李祥");
        System.out.println(ret);
end
    @Test
    public void test13() {
        //创建会话对象,用于和规则交互的引擎
        KieSession kieSession = kieBase.newKieSession();
        //讲数据交给规则引擎,规则迎请会根据提供的数据进行规则匹配
        kieSession.fireAllRules();
        //关闭会话
        kieSession.dispose();
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/71878.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

类与对象(上篇)

类与对象面向过程和面向对象类的引入类的定义类的访问限定符及封装访问限定符封装类的作用域类的实例化类对象类对象的存储方式类成员函数的this指针this指针的引出this指针的特性面向过程和面向对象 C语言是面向过程&#xff0c;注重的是过程&#xff0c;先分析求解问题的步骤…

【计算机视觉】目标检测中Faster R-CNN、R-FCN、YOLO、SSD等算法的讲解(图文解释 超详细必看)

觉得有帮助请点赞关注收藏~~~ 一、基于候选区域的目标检测算法 基于候选区域的深度卷积神经网络&#xff08;Region-based Convolutional Neural Networks&#xff09;是一种将深度卷积神经网络和区域推荐相结合的物体检测方法&#xff0c;也可以叫做两阶段目标检测算法。第一…

Web大学生网页作业成品——环保垃圾分类网站设计与实现(HTML+CSS+JavaScript) web前端开发技术 web课程设计 网页规划与设计

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

RFID标签让企业海量固定资产实现科学化管理

近年来&#xff0c;随着物联网、IoT、移动技术、云计算技术的成熟&#xff0c;越来越多的企业开始使用RFID标签管理企业海量的固定资产。优化固定资产标准化管理流程&#xff0c;有效管理和库存固定资产&#xff0c;进一步提高企业实物资产管理和库存效率。 包括资产申购、验收…

【操作系统】计算机大脑CPU

1.CPU组成机构和存储器层级 &#xff08;1&#xff09;CPU是计算机硬件系统的核心部件-大脑 结构&#xff1a;运算器控制器&#xff08;两个部件里面有寄存器组&#xff09;通过CPU内部的总线进行通信 &#xff08;2&#xff09;单核CPU架构 控制器Control Unit简称【CU】 …

Python使用Opencv图像处理方法完成手势识别(二)

Opencv完成手势识别根据坐标识别寻找最低点计算其他点与最低点的距离通过距离阈值判断手指根数和手势效果展现完整代码当我们把手近似出来后会得到一组轮廓的点坐标&#xff0c;我自己手势识别的思路就是根据点坐标来判断手势。根据坐标识别 寻找最低点 所谓寻找最低点&#…

浅谈Nacos注册中心集群分布式架构设计

前言 Nacos的压测性能是非常好的&#xff0c;这里是Nacos官方的压测报告。3节点(CPU 16核&#xff0c;内存32G)规模集群&#xff0c;压测容量服务数可达60W&#xff0c;实例注册数达110W&#xff0c;集群运行持续稳定&#xff0c;达到预期&#xff1b;注册/查询实例TPS达到 13…

ModStartBlog v6.3.0 任务调度重构,UEditor 升级

系统介绍 ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场&#xff0c;后台一键…

跨设备链路聚合 M-LAG

M-LAG&#xff08;Multichassis Link Aggregation Group&#xff09;即跨设备链路聚合组&#xff0c;是一种实现跨设备链路聚合的机制&#xff0c;如下图所示&#xff0c;将SwitchA和SwitchB通过peer-link链路连接并以同一个状态和Switch进行链路聚合协商&#xff0c;从而把链路…

学校介绍静态HTML网页设计作品 DIV布局学校官网模板代码 DW大学网站制作成品下载 HTML5期末大作业

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

iOS app上架app store流程详解​

前提条件​ 在有效期内的苹果开发者账号&#xff08;类型为个人或者公司账号&#xff09;。还有一种情况&#xff0c;就是你的Apple ID被添加到公司开发者账号团队里面&#xff0c;这样也是可以的&#xff0c;但是需要叫管理员给你开通相应的账号权限&#xff0c;如下截图&…

[附源码]Python计算机毕业设计Django在线图书销售系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

Vue | 有关Vue2路由知识点的一些总结,以及Vue3路由做出了哪些调整?

目录 Vue2: 1. 路由&#xff1a; 2. 路由规则&#xff1a; 3. 实现切换&#xff08;active-class可配置高亮样式&#xff09; 4. 指定展示位置 5. 路由的query参数 6. params传参&#xff1a; 7. 多级路由 8. 路由的props配置 9. 的replace属性 10. 编…

Android databinding之BindingMethod与BindingMethods介绍与使用(五)

一、介绍 前面几篇文章已介绍了很多data binding的用法&#xff0c;今天我将会介绍一个新的方法绑定BindingMethod的用法。 BindingMethod&#xff0c;从名字可以看出是绑定方法的&#xff0c;绑定的一般都是和布局有关&#xff0c;通过绑定来提高布局可扩展性。 二、使用 Bin…

把盏言欢,款款而谈,ChatGPT结合钉钉机器人(outgoing回调)打造人工智能群聊/单聊场景,基于Python3.10

就像黑火药时代里突然诞生的核弹一样&#xff0c;OpenAI的ChatGPT语言模型的横空出世&#xff0c;是人工智能技术发展史上的一个重要里程碑。这是一款无与伦比、超凡绝伦的模型&#xff0c;能够进行自然语言推理和对话&#xff0c;并且具有出色的语言生成能力。 好吧&#xff…

资产扫描神器ARL增强改造

拉取项目首先从GitHub克隆到服务器上。git clone https://github.com/ki9mu/ARL-plus-docker/修改配置文件因为ARL在配置文件里设置了黑名单&#xff0c;有时候项目为GOV或者EDU之类的时候无法进行扫描&#xff0c;所以在这里修改一下配置文件就可以解除限制。cd ARL-plus-dock…

Spring Boot3.0 GA系列全新版本-全新体验-学习案例1

SpringBoot3.0 GA 2022-11-24这是伟大的一天&#xff0c;Spring Boot进入了3.0时代&#xff0c;并会叩开JDK全面升级的浪潮 文章目录SpringBoot3.0 GA技术支持一、新建第一个mode&#xff1f;1.1、打开IDEA&#xff0c;新建项目1.2、选择 版本 和 依赖1.3、查看项目结构1.4、配…

vscode配置remote ssh

1. 安装插件 设置界面 右键最左边tab栏&#xff1a; 主体: vscode 插件: Remote SSH Linux主体: vscode-server 插件: C/C, CMake, CMake Tools, CodeLLDB, Rainbow Brackets, vscode-proto3, SVN 虚拟化主体: multipass linux发行版(比如ubuntu) 补充: multipass实例本地端口…

【C++ unordered_set set 和 unordered_map 和 map】

文章目录前言简单介绍哈希表&#xff0c;哈希结构什么时候用哈希表unordered_map操作likou第一题 两数之和unordered_set 基础操作unordered_set 实现总结前言 今天重新打开力扣&#xff0c;看到以前的签到题两数之和&#xff0c;以前的方法是双指针暴力解法&#xff0c;偶然看…

asp.net校园二手物品交易网站

目录 摘 要 Ⅰ Abstract Ⅱ 第一章 概述 1 1.1网站的开发背景 1 1.1.1学生二手物品交易置换网站的开发背景 1 1.1.2学生二手物品交易活动的现状 1 1.2 学生二手物品交易置换网站的研究方向和内容 2 1.2.1研究方向 2 1.2.2研究内容 2 1.3 学生二手物品交易置换网站的设计目标 2…