6. Drools高级语法

全套代码及资料全部完整提供,点此处下载

前面章节我们已经知道了一套完整的规则文件内容构成如下:

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

本章节我们就来学习其中的几个关键字。

6.1 global全局变量

global关键字用于在规则文件中定义全局变量,它可以让应用程序的对象在规则文件中能够被访问。可以用来为规则文件提供数据或服务。

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

在使用global定义的全局变量时有两点需要注意:

1、如果对象类型为包装类型时,在一个规则中改变了global的值,那么只针对当前规则有效,对其他规则中的global不会有影响。可以理解为它是当前规则代码中的global副本,规则内部修改不会影响全局的使用。

2、如果对象类型为集合类型或JavaBean时,在一个规则中改变了global的值,对java代码和所有规则都有效。

下面我们通过代码进行验证:

第一步:创建UserService类

package com.itheima.drools.service;

public class UserService {
public void save(){
System.out.println("UserService.save()...");
}
}

第二步:编写规则文件/resources/rules/global.drl

package testglobal
/*
此规则文件用于测试global全局变量
*/ global java.lang.Integer count //定义一个包装类型的全局变量
global com.itheima.drools.service.UserService userService //定义一个JavaBean类型的全局变量
global java.util.List gList //定义一个集合类型的全局变量 rule "rule_global_1"
when
then
count += 10; //全局变量计算,只对当前规则有效,其他规则不受影响
userService.save();//调用全局变量的方法
gList.add("itcast");//向集合类型的全局变量中添加元素,Java代码和所有规则都受影响
gList.add("itheima");
System.out.println("count=" + count);
System.out.println("gList.size=" + gList.size());
end rule "rule_global_2"
when
then
userService.save();
System.out.println("count=" + count);
System.out.println("gList.size=" + gList.size());
end

第三步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession(); //设置全局变量,名称和类型必须和规则文件中定义的全局变量名称对应
kieSession.setGlobal("userService",new UserService());
kieSession.setGlobal("count",5);
List list = new ArrayList();//size为0
kieSession.setGlobal("gList",list); kieSession.fireAllRules();
kieSession.dispose(); //因为在规则中为全局变量添加了两个元素,所以现在的size为2
System.out.println(list.size());

6.2 query查询

query查询提供了一种查询working memory中符合约束条件的Fact对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分并且以end结束。具体语法结构如下:

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

具体操作步骤:

第一步:编写规则文件/resources/rules/query.drl

package testquery
import com.itheima.drools.entity.Student
/*
此规则文件用于测试query查询
*/ //不带参数的查询
//当前query用于查询Working Memory中age>10的Student对象
query "query_1"
$student:Student(age > 10)
end //带有参数的查询
//当前query用于查询Working Memory中age>10同时name需要和传递的参数name相同的Student对象
query "query_2"(String sname)
$student:Student(age > 20 && name == sname)
end

第二步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession(); Student student1 = new Student();
student1.setName("张三");
student1.setAge(12); Student student2 = new Student();
student2.setName("李四");
student2.setAge(8); Student student3 = new Student();
student3.setName("王五");
student3.setAge(22); //将对象插入Working Memory中
kieSession.insert(student1);
kieSession.insert(student2);
kieSession.insert(student3); //调用规则文件中的查询
QueryResults results1 = kieSession.getQueryResults("query_1");
int size = results1.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results1) {
Student student = (Student) row.get("$student");
System.out.println(student);
} //调用规则文件中的查询
QueryResults results2 = kieSession.getQueryResults("query_2","王五");
size = results2.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results2) {
Student student = (Student) row.get("$student");
System.out.println(student);
}
//kieSession.fireAllRules();
kieSession.dispose();

6.3 function函数

function关键字用于在规则文件中定义函数,就相当于java类中的方法一样。可以在规则体中调用定义的函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。

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

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

具体操作步骤:

第一步:编写规则文件/resources/rules/function.drl

package testfunction
import com.itheima.drools.entity.Student
/*
此规则文件用于测试function函数
*/ //定义一个函数
function String sayHello(String name){
return "hello " + name;
} rule "rule_function_1"
when
$student:Student(name != null)
then
//调用上面定义的函数
String ret = sayHello($student.getName());
System.out.println(ret);
end

第二步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession(); Student student = new Student();
student.setName("小明"); kieSession.insert(student); kieSession.fireAllRules();
kieSession.dispose();

6.4 LHS加强

前面我们已经知道了在规则体中的LHS部分是介于when和then之间的部分,主要用于模式匹配,只有匹配结果为true时,才会触发RHS部分的执行。本章节我们会针对LHS部分学习几个新的用法。

6.4.1 复合值限制in/not in

复合值限制是指超过一种匹配值的限制条件,类似于SQL语句中的in关键字。Drools规则体中的LHS部分可以使用in或者not in进行复合值的匹配。具体语法结构如下:

Object(field in (比较值1,比较值2...))

举例:

$s:Student(name in ("张三","李四","王五"))
$s:Student(name not in ("张三","李四","王五"))

6.4.2 条件元素eval

eval用于规则体的LHS部分,并返回一个Boolean类型的值。语法结构如下:

eval(表达式)

举例:

eval(true)
eval(false)
eval(1 == 1)

6.4.3 条件元素not

not用于判断Working Memory中是否存在某个Fact对象,如果不存在则返回true,如果存在则返回false。语法结构如下:

not Object(可选属性约束)

举例:

not Student()
not Student(age < 10)

6.4.4 条件元素exists

exists的作用与not相反,用于判断Working Memory中是否存在某个Fact对象,如果存在则返回true,不存在则返回false。语法结构如下:

exists Object(可选属性约束)

举例:

exists Student()
exists Student(age < 10 && name != null)

可能有人会有疑问,我们前面在LHS部分进行条件编写时并没有使用exists也可以达到判断Working Memory中是否存在某个符合条件的Fact元素的目的,那么我们使用exists还有什么意义?

两者的区别:当向Working Memory中加入多个满足条件的Fact对象时,使用了exists的规则执行一次,不使用exists的规则会执行多次。

例如:

规则文件(只有规则体):

rule "使用exists的规则"
when
exists Student()
then
System.out.println("规则:使用exists的规则触发");
end rule "没有使用exists的规则"
when
Student()
then
System.out.println("规则:没有使用exists的规则触发");
end

Java代码:

kieSession.insert(new Student());
kieSession.insert(new Student());
kieSession.fireAllRules();

上面第一个规则只会执行一次,因为Working Memory中存在两个满足条件的Fact对象,第二个规则会执行两次。

6.4.5 规则继承

规则之间可以使用extends关键字进行规则条件部分的继承,类似于java类之间的继承。

例如:

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

6.5 RHS加强

RHS部分是规则体的重要组成部分,当LHS部分的条件匹配成功后,对应的RHS部分就会触发执行。一般在RHS部分中需要进行业务处理。

在RHS部分Drools为我们提供了一个内置对象,名称就是drools。本小节我们来介绍几个drools对象提供的方法。

6.5.1 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

6.5.2 getWorkingMemory

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

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

6.5.3 getRule

getRule方法的作用是返回规则对象。

package testgetRule
rule "rule_getRule"
when
then
System.out.println(drools.getRule());
end

6.6 规则文件编码规范

我们在进行drl类型的规则文件编写时尽量遵循如下规范:

  • 所有的规则文件(.drl)应统一放在一个规定的文件夹中,如:/rules文件夹
  • 书写的每个规则应尽量加上注释。注释要清晰明了,言简意赅
  • 同一类型的对象尽量放在一个规则文件中,如所有Student类型的对象尽量放在一个规则文件中
  • 规则结果部分(RHS)尽量不要有条件语句,如if(...),尽量不要有复杂的逻辑和深层次的嵌套语句
  • 每个规则最好都加上salience属性,明确执行顺序
  • Drools默认dialect为"Java",尽量避免使用dialect "mvel"

6.7 以上代码均在drools_quickstart项目中

第2-4-5章 规则引擎Drools高级语法-业务规则管理系统-组件化-中台的更多相关文章

  1. 小明历险记:规则引擎drools教程一

    小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...

  2. [Drools]JAVA规则引擎 -- Drools 2

    上一篇文章 http://blog.csdn.net/quzishen/archive/2011/01/25/6163012.aspx 描述了一些常用的drools的语法标签和一个模拟实例即发送积分的 ...

  3. [Drools]JAVA规则引擎 -- Drools

    Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  4. Java规则引擎drools:drt动态生成规则并附上具体项目逻辑

    一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...

  5. 开源规则引擎 drools

    java语言开发的开源业务规则引擎 DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用 ...

  6. 规则引擎drools封装

    一.前言 网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践 ...

  7. 开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule

    直接进入正题 我们在使用开源规则引擎 Drools 的时候, 启动的时候可能会抛出如下异常: Caused by: java.lang.ClassCastException: cn.com.cheng ...

  8. 使用规则引擎Drools计算圆周率PI

    实际上是使用规则引擎能够更新工作内存区重新匹配规则实现迭代功能. 使用了策略模式实现. <规则引擎与RETE算法介绍> PPT : http://files.cnblogs.com/lov ...

  9. JAVA规则引擎 -- Drools

    Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  10. 规则引擎 drools

    https://www.jianshu.com/p/725811f420db 深入了解Drools 简单介绍 笔者正在做风控系统,风控系统里边存在非常多的规则(比如:age < 16 || ag ...

随机推荐

  1. sklearn中MLPClassifier源码解析

    神经网络 .fit() 首先传入类私用方法._fit() 确定hidden_layer_size是可迭代的 调用_validate_hyperparameters验证超参数是否合法 验证输入的x和y是 ...

  2. 我的Vue之旅、01 深入Flexbox布局完全指南

    花了几个小时整合的"A Complete Guide to Flexbox"最新版本,介绍了flexbox的所有属性,外带几个实用的例子. 传统布局.Flexbox 布局的传统解决 ...

  3. PAT (Basic Level) Practice 1006 换个格式输出整数 分数 15

    让我们用字母 B 来表示"百".字母 S 表示"十",用 12...n 来表示不为零的个位数字 n(<10),换个格式来输出任一个不超过 3 位的正整数. ...

  4. python合并多个excel

    前言 1.工作中,经常需要合并多个Excel文件.如果文件数量比较多,则工作量大,易出错,此时,可以使用Python来快速的完成合并. 2.使用方法:将需要合并的多个Excel文件放到同一个文件夹下, ...

  5. 华为 Quidway S3700-28TP-SI-AC Routing Switch 配置时间(ntp)

    设置ntp服务器: [SW03] ntp unicast-server x.x.x.x 记住一定要退出特权模式之后再设置时区 <SW03>clock timezone beijing ad ...

  6. PHP全栈开发(八):CSS Ⅲ background

    设置背景颜色: div { background-color:#b0c4de; } 不仅可以给body标签设置背景颜色,还能给p,div,h标签设置背景颜色 设置背景图片: body { backgr ...

  7. StampedLock:一个并发编程中非常重要的票据锁

    摘要:一起来聊聊这个在高并发环境下比ReadWriteLock更快的锁--StampedLock. 本文分享自华为云社区<[高并发]一文彻底理解并发编程中非常重要的票据锁--StampedLoc ...

  8. 2022网刃杯ics

    ​ 目录 easyiec Ncsubj 喜欢移动的黑客 xyp07 ICS6-LED_BOOM 根据大佬的wp后,自己做了一遍 这次学到很多东西 ICS easyiec tcp追踪流直接能看到 ​编辑 ...

  9. JSTL组件的下载链接地址

    配置JSTL和下载jar包 JSTL的安装包 下载地址:http://tomcat.apache.org/download-taglibs.cgi 在下载页面找到JSTL的规范和实现的两个jar包,如 ...

  10. HTML+CSS基础知识(5)相对定位、绝对定位、固定定位

    文章目录 1.相对定位 1.1 代码 1.2 测试结果 2.绝对定位 2.1 代码 2.2 测试 3.固定定位 3.1 代码 3.2 测试结果 1.相对定位 1.1 代码 <!DOCTYPE h ...