规则引擎入门-基于easy-rules

这篇具有很好参考价值的文章主要介绍了规则引擎入门-基于easy-rules。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概念理解

描述一个简单的处理:基于一堆现实情况,运用规则引擎、经过处理得到对应的结果,然后再据此做后续的事情

  • fact: 事实,已有的现实情况,即输入信息
  • rules: 规则集合,由一系列规则组成,可能有不同的规则排列
  • rule: 规则,包含基本的判断条件和条件符合要做的动作。
  • condition: 规则的判定条件(特定的判断逻辑 if else)
  • action: 规则判定符合后执行的动作
    规则引擎入门-基于easy-rules

实例和编码

一句话描述: 提着去酒店买酒,需要判断是否成年人,成年人才能购买酒,商店据此卖你酒,你买到了酒就装包里走人,回家喝酒去

接下来看easy-rules的定义和处理。

抽象出2条规则

@Rule(name = "age-rule", description = "age-rule", priority = 1)
public class AgeRule {

    @Condition
    public boolean isAdult(@Fact("person") Person person) {
        return person.getAge() > 18;
    }

    @Action
    public void setAdult(@Fact("person") Person person) {
        person.setAdult(true);
    }
}
package org.jeasy.rules.tutorials.shop;

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;

/**
 * @author dingqi on 2023/5/26
 * @since 1.0.0
 */
@Rule(name = "alcohol-rule", description = "alcohol-rule", priority = 2)
public class AlcoholRule {

    @Condition
    public boolean shopRule(@Fact("person") Person person) {
        return person.isAdult() == true;
    }

    @Action
    public void shopReply(@Fact("bag") Bag bag) {
        bag.setSuccess(true);
        bag.add("Vodka");
    }
}

简单的规则引擎

// create a rule set
Rules rules = new Rules();
rules.register(new AgeRule());
rules.register(new AlcoholRule());

//create a default rules engine and fire rules on known facts
DefaultRulesEngine rulesEngine = new DefaultRulesEngine();

事实1的处理

Facts facts = new Facts();
Person tom = new Person("Tom", 19);
facts.put("person", tom);
Bag bag = new Bag();
facts.put("bag", bag);

System.out.println("Tom: Hi! can I have some Vodka please?");
rulesEngine.fire(rules, facts);
System.out.println("Tom: bag is " + bag);

输出:Tom成年了,买到了伏特加

Tom: Hi! can I have some Vodka please?
Tom: bag is Bag{success=true, goods=[Vodka]}

事实2的处理

Person jack = new Person("Jack", 10);
facts.put("person", jack);
Bag bag2 = new Bag();
facts.put("bag", bag2);

System.out.println("Jack: Hi! can I have some Vodka please?");
rulesEngine.fire(rules, facts);
System.out.println("Jack: bag is " + bag2);

输出:Jack未成年,无功而返

Jack: Hi! can I have some Vodka please?
Jack: bag is Bag{success=false, goods=[]}

easy-rules 规则的抽象和执行

事实描述

public class Facts implements Iterable<Fact<?>> {

    private final Set<Fact<?>> facts = new HashSet<>();

/**
 * A class representing a named fact. Facts have unique names within a {@link Facts}
 * instance.
 * 
 * @param <T> type of the fact
 * @author Mahmoud Ben Hassine
 */
public class Fact<T> {
	
	private final String name;
	private final T value;

事实简单就是key、value对, 某个事实的名称,和事实的属性特征(以一切皆对象来看,就是一个一个的对象组成了事实)。(只要在规则条件真正执行前,能明确这些事实就行)

规则的抽象

  • 名称
  • 描述
  • 优先级
  • 执行Facts的的方法

org.jeasy.rules.api.Rule接口 和基础实现类org.jeasy.rules.core.BasicRule

条件和动作注解:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Condition {

}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Condition {

}
默认的规则
class DefaultRule extends BasicRule {

    private final Condition condition;
    private final List<Action> actions;

    DefaultRule(String name, String description, int priority, Condition condition, List<Action> actions) {
        super(name, description, priority);
        this.condition = condition;
        this.actions = actions;
    }

    @Override
    public boolean evaluate(Facts facts) {
        return condition.evaluate(facts);
    }

    @Override
    public void execute(Facts facts) throws Exception {
        for (Action action : actions) {
            action.execute(facts);
        }
    }

}

动态代理执行规则和动作

使用org.jeasy.rules.api.Rules添加规则时如下:

  • org.jeasy.rules.api.Rules#register
 public void register(Object... rules) {
     Objects.requireNonNull(rules);
     for (Object rule : rules) {
         Objects.requireNonNull(rule);
         this.rules.add(RuleProxy.asRule(rule));
     }
 }

使用org.jeasy.rules.annotation.Rule注解构造的规则是使用RuleProxy构造的
规则引擎入门-基于easy-rules

规则的执行:org.jeasy.rules.core.DefaultRulesEngine#doFire
void doFire(Rules rules, Facts facts) {
    if (rules.isEmpty()) {
        LOGGER.warn("No rules registered! Nothing to apply");
        return;
    }
    logEngineParameters();
    log(rules);
    log(facts);
    LOGGER.debug("Rules evaluation started");
    for (Rule rule : rules) {
        final String name = rule.getName();
        final int priority = rule.getPriority();
        if (priority > parameters.getPriorityThreshold()) {
            LOGGER.debug("Rule priority threshold ({}) exceeded at rule '{}' with priority={}, next rules will be skipped",
                    parameters.getPriorityThreshold(), name, priority);
            break;
        }
        if (!shouldBeEvaluated(rule, facts)) {
            LOGGER.debug("Rule '{}' has been skipped before being evaluated", name);
            continue;
        }
        boolean evaluationResult = false;
        try {
            evaluationResult = rule.evaluate(facts);
        } catch (RuntimeException exception) {
            LOGGER.error("Rule '" + name + "' evaluated with error", exception);
            triggerListenersOnEvaluationError(rule, facts, exception);
            // give the option to either skip next rules on evaluation error or continue by considering the evaluation error as false
            if (parameters.isSkipOnFirstNonTriggeredRule()) {
                LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");
                break;
            }
        }
        if (evaluationResult) {
            LOGGER.debug("Rule '{}' triggered", name);
            triggerListenersAfterEvaluate(rule, facts, true);
            try {
                triggerListenersBeforeExecute(rule, facts);
                rule.execute(facts);
                LOGGER.debug("Rule '{}' performed successfully", name);
                triggerListenersOnSuccess(rule, facts);
                if (parameters.isSkipOnFirstAppliedRule()) {
                    LOGGER.debug("Next rules will be skipped since parameter skipOnFirstAppliedRule is set");
                    break;
                }
            } catch (Exception exception) {
                LOGGER.error("Rule '" + name + "' performed with error", exception);
                triggerListenersOnFailure(rule, exception, facts);
                if (parameters.isSkipOnFirstFailedRule()) {
                    LOGGER.debug("Next rules will be skipped since parameter skipOnFirstFailedRule is set");
                    break;
                }
            }
        } else {
            LOGGER.debug("Rule '{}' has been evaluated to false, it has not been executed", name);
            triggerListenersAfterEvaluate(rule, facts, false);
            if (parameters.isSkipOnFirstNonTriggeredRule()) {
                LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");
                break;
            }
        }
    }
}

默认的规则引擎直接遍历规则去执行,如果condition执行命中后,则去执行action

public class RuleProxy implements InvocationHandler

规则引擎入门-基于easy-rules

private Object evaluateMethod(final Object[] args) throws IllegalAccessException, InvocationTargetException {
    Facts facts = (Facts) args[0];
    Method conditionMethod = getConditionMethod();
    try {
        List<Object> actualParameters = getActualParameters(conditionMethod, facts);
        return conditionMethod.invoke(target, actualParameters.toArray()); // validated upfront
    } catch (NoSuchFactException e) {
        LOGGER.warn("Rule '{}' has been evaluated to false due to a declared but missing fact '{}' in {}",
                getTargetClass().getName(), e.getMissingFact(), facts);
        return false;
    } catch (IllegalArgumentException e) {
        LOGGER.warn("Types of injected facts in method '{}' in rule '{}' do not match parameters types",
                conditionMethod.getName(), getTargetClass().getName(), e);
        return false;
    }
}
规则执行监听器

在规则执行的过程中,可以做各种操作。可以看成规则的扩展点

/**
 * A listener for rule execution events.
 *
 * @author Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
 */
public interface RuleListener {

    /**
     * Triggered before the evaluation of a rule.
     *
     * @param rule being evaluated
     * @param facts known before evaluating the rule
     * @return true if the rule should be evaluated, false otherwise
     */
    default boolean beforeEvaluate(Rule rule, Facts facts) {
        return true;
    }

    /**
     * Triggered after the evaluation of a rule.
     *
     * @param rule that has been evaluated
     * @param facts known after evaluating the rule
     * @param evaluationResult true if the rule evaluated to true, false otherwise
     */
    default void afterEvaluate(Rule rule, Facts facts, boolean evaluationResult) { }

    /**
     * Triggered on condition evaluation error due to any runtime exception.
     *
     * @param rule that has been evaluated
     * @param facts known while evaluating the rule
     * @param exception that happened while attempting to evaluate the condition.
     */
    default void onEvaluationError(Rule rule, Facts facts, Exception exception) { }

    /**
     * Triggered before the execution of a rule.
     *
     * @param rule the current rule
     * @param facts known facts before executing the rule
     */
    default void beforeExecute(Rule rule, Facts facts) { }

    /**
     * Triggered after a rule has been executed successfully.
     *
     * @param rule the current rule
     * @param facts known facts after executing the rule
     */
    default void onSuccess(Rule rule, Facts facts) { }

    /**
     * Triggered after a rule has failed.
     *
     * @param rule the current rule
     * @param facts known facts after executing the rule
     * @param exception the exception thrown when attempting to execute the rule
     */
    default void onFailure(Rule rule, Facts facts, Exception exception) { }

}

回顾规则执行和监听器的执行过程

// 1. 条件执行前
triggerListenersBeforeEvaluate(rule, facts);
try {
	evaluationResult = rule.evaluate(facts);
} catch(Exception e){
	 // 2. 条件执行失败
	 triggerListenersOnEvaluationError(rule, facts, exception);
}

if (evaluationResult) {
	// 3. 条件执行后(条件满足)
	triggerListenersAfterEvaluate(rule, facts, true);
	 try {
	 	  // 4. 动作执行前
	 	  triggerListenersBeforeExecute(rule, facts);
          rule.execute(facts);
          // 5. 动作执行后
          triggerListenersOnSuccess(rule, facts);
	 } catch (Exception exception) {
	 	 // 6. 条件执行失败
	 	 triggerListenersOnFailure(rule, exception, facts);
	 }
}else{
	// 3. 条件执行后(条件不满足)
	triggerListenersAfterEvaluate(rule, facts, false);
}

扩展

  1. Java Expression Language (JEXL) :表达式语言引擎

https://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/JexlEngine.html

  1. MVEL:一个功能强大的基于Java应用程序的表达式语言。

  2. SpEL:Spring表达式语言文章来源地址https://www.toymoban.com/news/detail-466216.html

name: adult rule
description: when age is greater than 18, then mark as adult
priority: 1
condition: "#{ ['person'].age > 18 }"
actions:
  - "#{ ['person'].setAdult(true) }"

到了这里,关于规则引擎入门-基于easy-rules的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Easy Rules规则引擎(1-基础篇)

    最近团队在做一些 Visa 、 Master 卡的交易风控,运营团队提供了一些交易风控的规则,比如针对卡号MCC设置单笔交易限额,24小时交易限额,72小时交易限额等等,还有触发风控规则是否拦截交易还是只发告警邮件等等等。 虽然写各种条件判断也能实现,但是随着后面规则增加

    2024年02月12日
    浏览(36)
  • python轻量规则引擎rule-engine入门与应用实践

    rule-engine是一种轻量级、可选类型的表达式语言,具有用于匹配任意 Python 对象的自定义语法,使用python语言开发。 规则引擎表达式用自己的语言编写,在 Python 中定义为字符串。其语法与 Python 最相似,但也受到 Ruby 的一些启发。这种语言的一些特性包括: 可选类型提示 用

    2024年02月04日
    浏览(44)
  • Java源码规则引擎:jvs-rules 8月新增功能介绍

    JVS-rules是JAVA语言下开发的规则引擎,是jvs企业级数字化解决方案中的重要配置化工具,核心解决业务判断的配置化,常见的使用场景:金融信贷风控判断、商品优惠折扣计算、对员工考核评分等各种变化的规则判断情景。 8月是收获的季节,jvs-rules在这个季节到来之时做了大

    2024年02月14日
    浏览(44)
  • 低代码开发重要工具:jvs-rules 规则引擎功能介绍(三)

    规则引擎是由多个组件组成的,这些组件共同协作实现规则的管理、执行和决策流的构建。 决策流:决策流是由多个业务节点连接而成的流程,用于实现复杂的业务逻辑。决策流中的业务节点按照特定的顺序执行,每个节点根据输入数据和规则引擎的执行结果,决定下一个要

    2024年02月15日
    浏览(49)
  • jvs-rules(规则引擎)1.23功能更新说明,新增SQL变量、数据源等

    1、新增SQL变量: SQL变量通常指的是在执行SQL查询时使用的动态变量。这些变量允许在查询中注入或更改某些值,以便根据不同的条件或输入执行不同的查询。 1.1 新增自定义SQL语言进行数据查询; 用户可以使用自定义的SQL语句来查询数据。通过这种方式,用户可以在规则中

    2024年01月25日
    浏览(49)
  • 《基于 Vue 组件库 的 Webpack5 配置》2.模块规则 module.rule

    配置 module.rules ,创建模块时,匹配请求的规则数组; 可参考 webpack5 指南-管理资源; vue 可参考上述配置; js 使用 webpack babel-loader; css 参考 webpack 加载 CSS。注意 style-loader 和 vue-style-loader 选一个即可,两者的功能基本一致,只是 vue-style-loader 可用于服务端渲染 SSR; stylus

    2024年02月11日
    浏览(47)
  • LiteFlow规则引擎的入门

    1、LiteFlow简介 LiteFlow是一个非常强大的现代化的规则引擎框架,融合了编排特性和规则引擎的所有特性。 利用LiteFlow,你可以将瀑布流式的代码,转变成以组件为核心概念的代码结构,这种结构的好处是可以任意编排,组件与组件之间是解耦的,组件可以用脚本来定义,组件

    2024年02月05日
    浏览(41)
  • 【规则引擎】Drools急速入门

    1.Drools规则引擎简介 (1)什么是规则引擎 ​ 全称为业务规则管理系统,英⽂名为BRMS(即 Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理

    2024年02月05日
    浏览(33)
  • Java规则引擎Drools急速入门

    1.Drools规则引擎简介 (1)什么是规则引擎 ​ 全称为业务规则管理系统,英⽂名为BRMS(即 Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理

    2024年02月04日
    浏览(58)
  • 【游戏引擎Easy2D】基于基础类型展开的监听器学习详解

       🧛‍♂️ iecne个人主页: 点赞关注收藏评论支持哦~ 💡每天 关注 iecne的作品,一起进步 👉本文收录 专栏 :【C++游戏引擎】 🐳希望大家多多支持🥰一起进步呀! 哈喽大家好,我是 iecne ,本期为大家带来的是CPP/C++【游戏引擎Easy2D】一篇打通引擎顶级类型,Listener。包

    2024年01月17日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包