栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

drools教程(drools语法)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

drools教程(drools语法)

背景

在银行办理贷款的过程中,你会被要求填写各种个人信息,包括住房情况,车辆情况,收入情况等等。银行会根据这些情况根据银行内部业务规则给出1个贷款额度。

代码实现贷款业务规则:

public String getLoan(LoanApply loana){
	// 失信人员,不具有放贷资格
	if(loana.isDishonest){
		return "不具备贷款资格";
	}
	
	// 月薪3000以下且没有小车且没有住房,不具有贷款资格
	if(loana.getSalary()<3000 && !loana.hasCar() && !loana.hasHouse()){
		return "不具备贷款资格";
	}
	
	// 有住房且有小车且月薪3000以下,贷款额度10万元
	if(loana.hasHouse && loana.hasCar && loana.getSalary < 3000){
		return "贷款额度10万元"
	}
	
	// 有住房且有小车且月薪3000到5000元,贷款额度12万元
	if(loana.hasHouse && loana.hasCar && loana.getSalary > 3000 && loana.getSalary < 5000){
		return "贷款额度12万元"
	}
	
	// 有住房且没有小车的人且月薪3000元一下,贷款额度5万元
	if(loana.hasHouse && !loana.hasCar && loana.getSalary < 3000){
		return "贷款额度5万元"
	}
	
	//...实际的贷款额度规则比这个更加复杂
}
问题解决
业务规则变化(增删改)时需要系统重启不重启程序情况下应用规则
业务规则与系统代码耦合在一起分离业务规则和系统代码
业务规则有程序语言实现,非程序员修改困难使用简单的语言实现规则
规则引擎

是什么:英文名BRMS(Business Rule Management System)业务规则管理系统,不是框架
作用:分类业务规则和系统代码。输入数据对象,根据业务规则处理,输出业务决策
开源产品:drools等等
好处:

动态:修改业务规则不重启系统即可启用分离:分离业务规则和系统代码简单:非程序员也可以编写规则文件维护:面对新的业务规则修改规则文件即可
适用:业务规则经常变化 drools

是什么:jBoss提供的属于kie下子项目,java语言开发的开源规则引擎
有什么:规则文件(*.drl),fact对象,工作内存,匹配器,执行引擎
作用:

使用规则文件分类业务规则和系统代码业务规则修改后不用重启系统即可生效 drools入门

pom.xml

 

meta-INF/kmodule.xml



    
    
        
        
    

fact对象

public class LoanApply {
    private boolean dishonest;

    public boolean isDishonest() {
        return dishonest;
    }

    public void setDishonest(boolean dishonest) {
        this.dishonest = dishonest;
    }
}

rules/loan.drl

// 逻辑包名
package loan
// 引入java对象
import xcrj.entity.LoanApply

// 规则名要唯一
rule "rule_loan_1"
	when
		// $order是LoanApply对象名
		// 括号内结果必须为true或false
		$loan:LoanApply(dishonest)
	then
		System.out.println("不具备贷款资格");
end

unit test

public class RuleLoanTest {
    @Test
    public void testQuickStart() {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact对象 规则引擎所需输入对象
        LoanApply loan = new LoanApply();
        loan.setDishonest(true);
        // 注入fact对象 到规则引擎的工作内存
        session.insert(loan);
        // 触发所有规则 进行模式匹配
        session.fireAllRules();
        // 关闭会话
        session.dispose();
    }
}
drools使用

入门案例小结:

步骤作用
pom.xml drools-compilerdrools依赖
meta-INF/kmodule.xmlkbase ksession rule文件位置
fact对象规则引擎输入对象
rules/loan.drlrule when then end,when匹配规则then执行规则
unit testKieServices KieContainer KieSession fact kieSession.insert kieSession.fire***Rule kieSession.dispose


drools kie核心类调用关系

KieServicesKieRepositoryKieContianerKieSessionKiebaseKieProject
drools组成

working memory(工作内存):存储fact对象
rule base(规则库):存储rule
inference engine(推理引擎)

pattern matcher(匹配器):fact 匹配(when下语句LHS括号中pattern) ruleagenda(议程):存储匹配成功的factexecution engine(执行引擎):执行then下语句

drools rule语法 规则文件结构
package 逻辑包名
import java对象或静态方法
global 全局变量
function 自定义函数
query 查询
rule end 规则体
global 全局变量

注意:

在drl文件中定义全局变量后,需要在java文件中赋值全局变量为包装类时,对该包装类全局变量的改变只在当前rule中有效,在java代码中也无效全局变量为普通javaBean,集合类时,对该包装类全局变量的改变在当前drl中的所有rule中有效,在java代码中也有效

在drl文件中设置全局变量

该drl文件中所有rule都可以使用该全局变量java代码中也可以使用drl中定义的全局变量

global 包装类
drl

package  testglobal
import java.lang.Integer

global Integer num;

rule "rule_global_integer1"
    when
    then
        // 包装类型 修改global变量,只对当前规则生效
        num+=15;
        // 输出20=5+15
        System.out.println("rule_global_integer1, num="+num);
end


rule "rule_global_integer2"
    when
    then
    	// 输出5
        System.out.println("rule_global_integer2, num="+num);
end

java

	@Test
    public void testGlobalInteger() {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact 规则引擎所需输入对象
        // 为global变量赋初始值
        session.setGlobal("count", 5);
        // 模式匹配 触发所有规则
        session.fireAllRules();
        // 获取global变量
        Integer num = (Integer) session.getGlobal("num");
		 输出5
        System.out.println("in java num: " + num);
        // 关闭会话
        session.dispose();
    }

global 集合类

package  testglobal
import java.util.List

global List list;

rule "rule_global_list1"
    when
    then
        list.add("456");
        // 输出2
        System.out.println("激活rule_global_list1,list.size="+list.size());
end

// gobal list
rule "rule_global_list2"
    when
    then
        // 输出2
        System.out.println("激活rule_global_list2,list.size="+list.size());
end

java

	@Test
    public void testGlobalList() {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact 规则引擎所需输入对象
        // 为global变量赋初始值
        List list = new ArrayList<>();
        list.add("123");
         输出1
        System.out.println("list.size=" + list.size());
        session.setGlobal("list", list);
        // 模式匹配 触发所有规则
        session.fireAllRules();
         输出2
        System.out.println("list.size=" + list.size());
        // 关闭会话
        session.dispose();
    }
function 自定义函数

作用:封装处理逻辑
语法

function 返回类型 "函数名"(入参){

}

示例
drl:

package testfunc

function String sayHi(String name){
    return "hi "+name;
}

rule "rule_func"
    when
    then
    	// 调用函数
        String str=sayHi("xcrj");
        System.out.println("rule_func 被触发:"+str);
end
query 查询

作用:用来查询working memory中的fact
语法

query "query_name"(optional param)
	LHS
end

用来查询working memory中的fact仅仅包含规则文件中LHS部分

示例
drl:

package testquery
import xcrj.Student

// 无参查询
query "query1"
    $student:Student(age==18)
end
// 有参查询
query "query2"(String sname)
    $student:Student(age==18 && name.equals(sname))
end

java:

	@Test
    public void testQuery() {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact 规则引擎所需输入对象
        Student student1 = new Student();
        student1.setAge(18);
        student1.setName("xcrj01");
        Student student2 = new Student();
        student2.setAge(18);
        student2.setName("xcrj02");
        // 注入fact 到规则引擎工作内存
        session.insert(student1);
        session.insert(student2);
        // 执行查询 query1
        QueryResults queryResults = session.getQueryResults("query1");
        int size = queryResults.size();
        System.out.println("query1查询结果 size=" + size);
        for (QueryResultsRow row : queryResults) {
            Student s = (Student) row.get("$student");
            System.out.println("query1查询结果" + "student name=" + s.getName() + "student age:" + s.getAge());
        }
        // rule query2
        QueryResults queryResult2s = session.getQueryResults("query2", "xcrj02");
        int size2 = queryResult2s.size();
        System.out.println("query2查询结果 size=" + size2);
        for (QueryResultsRow row : queryResults) {
            Student s = (Student) row.get("$student");
            System.out.println("query2查询结果" + "student name=" + s.getName() + "student age:" + s.getAge());
        }
        // 模式匹配 触发所有规则
        session.fireAllRules();
        // 关闭会话
        session.dispose();
    }
rule语法结构
//规则体语法结构
rule "rule_name"
	attributes
	when
		LHS// left hand side,rule条件部分;LHS为空表示true
	then
		RHS// right hand side,rule执行部分
end

LHS由多个条件组成条件=patternpattern结构:绑定变量名:javaBean(field 约束)`field约束:pattern括号内部内容,field约束结果必须为true或false绑定变量名:$loan:LoanApply($dh:dishonest)中的$loan,以$开头绑定属性名:$loan:LoanApply($dh:dishonest)中的$dh,以$开头 继承rule

作用:and拼接LHS

rule "rule1"
	when
		Student(age>10)
	then
		System.out.println("rule1被触发");
end

rule "rule2" extends "rule1"
	when
		// 实际相当 age>10 && age<20
		Student(age<20)
	then
		System.out.println("rule2被触发");
end
attributes 属性
属性作用示例
enabled规则是否启用enabled false
dialect语言,默认java,可选mveldialect "java"
saliencerule优先级,越大优先级越高,优先级相同从上到下匹配执行salience 10
no-loop防止内置函数造成的死循环no-loop true
activation-group相同分组名rule只能有1个被执行,优先级相同执行前面的,不同执行高的activation-group "activationgroup01"
agenda-group议程分组,获取到关注的议程分组中的规则匹配后都能被执行drlagenda-group "agendagroup01" javasession.getAgenda().getAgendaGroup("agenda_group1").setFocus();
auto-focus设置同组agenda自动被关注,一组只要有1个被设置为true即可auto-focus true
timer支持1.java.util.Timer 2.cron表达式drl 1.timer (4s 2s) 2.timer (cron:0/5 * * * * ?)
java kieSession持续触发规则引擎
date-effective生效时间,默认格式dd-MM-yyyy,自定义格式yyyy-MM-dd hh:mm:ss
date-expires失效时间,当前时间<设置的时间才生效用法同于date-effective

agenda-group:
drl:

package agendagroup

rule "rule_agenda_group1"
    agenda-group "agenda_group1"
	when
	then
		System.out.println("成功匹配到rule_agenda_group1");
end

rule "rule_agenda_group2"
    agenda-group "agenda_group1"
	when
	then
		System.out.println("成功匹配到rule_agenda_group2");
end

test:

    @Test
    public void testAttribteAgendaGroup() {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact 规则引擎所需输入对象
        // 注入fact 
        // 关注某个agenda-group
        session.getAgenda().getAgendaGroup("agenda_group1").setFocus();
        // 触发所有规则
        session.fireAllRules();
        // 关闭会话
        session.dispose();
    }

timer:
drl:

package testtimer

// java.util.timer
rule "timer_timer"
    timer (4s 2s)
	when
	then
		System.out.println("成功匹配到timer_timer");
end

// cron表达式
rule "timer_cron"
    timer (cron:0/5 * * * * ?)
	when
	then
		System.out.println("成功匹配到timer_cron");
end

java:

    @Test
    public void testAttributeTimer() throws InterruptedException {
        // KieServices
        KieServices kieServices = KieServices.Factory.get();
        // KieContainer
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // KieSession
        KieSession session = kieContainer.newKieSession();
        // 构造fact 规则引擎所需输入对象
		// 注入fact 
		// 新线程,触发规则进行规则匹配,直到调用halt方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                session.fireUntilHalt();
            }
        }).start();
		 原线程,睡眠
        Thread.sleep(10000);
        session.halt();
        // 关闭会话
        session.dispose();
    }
field 操作符
操作符作用
java操作符一般都可使用
contiansfield是字符串/集合 包含
not contiansfield是字符串/集合 不包含
memberOffield是集合的成员
not memberOffield不是集合的成员
matchesfield匹配正则表达式
not matchesfield不匹配正则表达式
in$stu:Student(name in ("xcrj01","xcrj02"))
not in$stu:Student(name not in ("xcrj01","xcrj02"))
增加LHS
增强说明示例
eval(表达式)eval(1==1)
not fact工作内存没有这个fact返回truenot Stuent(age==18)
exists fact工作内存存在任一1个满足条件fact返回true,then后执行1次,没用exists且有多个条件满足时执行多次thenexists Student(age>10)

eval

rule "rule1"
    when
    	// eval(表达式),
        eval(true)
    then
        System.out.println("rule1被触发");
end
增加RHS
增强说明
drools.halt()终止后面所有rule的执行
drools.getWorkingMemory()获取工作内存对象,本质上是kieSession对象
drools.getRule()获取当前rule对象
drools内置方法会再匹配
    使用在RHS中即then之下使用内置方法后匹配器会重新匹配fact和rule使用内置方法需要注意避免死循环
内置方法作用
insert(xcrj);往工作内存中插入fact
retract($xcrj)从工作内存中撤回fact
update($xcrj);更新工作内存中的fact

示例

rule "rule_loan_1"
	when
		$loan:LoanApply(dishonest)
	then
		$loan.setDishonest(false)
		update($loan)
		System.out.println("不具备贷款资格");
end
drools匹配所有规则
kieSession.fireAllRules();
drools匹配特定规则
// 规则名相等
kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule_loan01"));
// 规则名开头
session.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_"));
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/775820.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号