Easy Rules core包 规则引擎

概述:

1、依赖:可以只引入core包即可使用规则引擎;

以引入easy-rules-support。支持XOR logic、json描述规则、yaml描述规则。

如果要使用SpEL(Spring Expression Language)、MVEL(表达式解析器)则还需要引入easy-rules-spel[4.1.0开始引入]、easy-rules-mvel

<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>4.0.0</version>
</dependency>

包结构

  • 注解包:org.jeasy.rules.annotation
  • API:org.jeasy.rules.api

  • 核心包:org.jeasy.rules.core

1、org.jeasy.rules.annotation

a)     注解说明(可能解释不够准确,详细参照作者注释)

名称

描述

说明

Action 规则行为注解 
  • 只能给无参public修饰符方法使用该注解
  • 规则引擎会忽略方法返回值
  • order属性设置规则行为执行顺序
Condition 规则条件注解 
  • 只能给无参且返回boolean值的公共方法
Fact 参数标记设置为fact注解 
  • 作为Condition或者Action的参数
Priority 规则优先级 
  • 只能注解无参并且返回integer值的公共方法
Rule 

将类标记为规则类

  • 属性name:规则注册器内唯一
  • 属性description:规则描述
  • 属性priority:规则优先级

b)     使用举例:

代码示例

说明

@Rule(name = "FactRule", description = "示例",priority = 1)
public static class FactRule {
    @Condition
  public boolean when(@Fact("fact") Fact fact) {
       return true;
    }
    @Action
 public void then(@Fact("fact") Fact fact) {
       //TO DO
    }
}

@Rule注解:注解类FactRule为一个rule。有三个属性:

name:规则名称,必须唯一,同名rule,注册到rules中会被覆盖

descrption:规则描述

priority:执行优先级,注册到rules是会根据priority排序

每个Rule中必须要有一个 @Condition和一个 @Action。

 当@Condition注释的方法返回true时,会执行@Action注释的方法;否则,不执行。

2、org.jeasy.rules.api

a)       函数式接口Action:规则行为接口

  • void execute(Facts facts) throws Exception:当规则的条件计算为true时执行操作
  • 参数:facts
  • 不能执行时抛出异常

b)      函数式接口Condition:规则条件接口

  • boolean evaluate(Facts facts):根据已知事实评估情况。

c)       Rule:可由规则引擎触发的规则的抽象。

d)      Facts与Fact:参数

e)      RuleListener:用于规则执行事件的侦听器

  • default boolean beforeEvaluate(Rule rule, Facts facts) :在规则的evaluate前触发,如果rule的condition需要执行返回true,否则返回false
  • default void afterEvaluate(Rule rule, Facts facts, boolean evaluationResult):在规则evaluate后触发
  • default void onEvaluationError(Rule rule, Facts facts, Exception exception):在规则condition的evaluate(求值)过程中发生异常
  • default void beforeExecute(Rule rule, Facts facts):规则execute前触发
  • default void onSuccess(Rule rule, Facts facts):规则execute执行成功
  • default void onFailure(Rule rule, Facts facts, Exception exception):规则execute执行失败

f)        Rules:封装一组Rule :private Set<Rule> rules = new TreeSet<>(); 感兴趣的可以研究下TreeSet的实现,研究透彻了会对Tree有

g)      RulesEngineParameters——【参照引擎DefaultRulesEngine,对引擎参数的使用】

  • public static final int DEFAULT_RULE_PRIORITY_THRESHOLD:默认优先级阈值, 默认值:Integer.MAX_VALUE
  • private boolean skipOnFirstAppliedRule:当一个规则被应用时,跳过下一个适用的规则
  • private boolean skipOnFirstNonTriggeredRule:当一个规则没有被触发时,跳过下一个适用的规则
  • private boolean skipOnFirstFailedRule:当一个规则失败时,跳过下一个适用的规则
  • private int priorityThreshold:优先级超过用户定义的阈值,默认值DEFAULT_RULE_PRIORITY_THRESHOLD。

h)      RulesEngineListener:在Evaluate之前或者之后,监听每个rules迭代

  • default void beforeEvaluate(Rules rules, Facts facts)
  • default void afterExecute(Rules rules, Facts facts)

i)        RulesEngine:规则引擎接口

  • RulesEngineParameters getParameters():获取规则引擎参数
  • default List<RuleListener> getRuleListeners():获取规则监听器
  • default List<RulesEngineListener> getRulesEngineListeners():获取规则引擎监听器
  • void fire(Rules rules, Facts facts):规则引擎启动
  • default Map<Rule, Boolean> check(Rules rules, Facts facts):启动前检查rule

3、org.jeasy.rules.core

a)       abstract class AbstractRulesEngine implements RulesEngine:规则引擎实现,未实现fire和check,跟具体规则引擎有关;如果需要自定义规则引擎,可以继承该类。

b)      Easy Rules默认实现规则:

public final class DefaultRulesEngine extends AbstractRulesEngine

说明:

  • 规则是根据它们PRIORITY属性的自然顺序(由小到大)触发的。
  • 该实现遍历已排序的规则集,计算每个规则的条件,并在条件为真时执行其操作。
  • 实际上是不是根据PRIORITY属性排序,要看Rule实现类的compareTo()的实现;不建议修改。

代码关注点:dofire()

Q1、doFire()中直接通过for each迭代rules,如何通过priority控制优先级?----注册时TreeSet();

Q2、RulesEngineParameters属性使用?------根据引擎参数配置跳过规则,如果自己实现引擎的话,需要考虑这些参数的业务,如果不是的话,需要了解默认引擎如何使用该参数

@Override
public void fire(Rules rules, Facts facts) {
    triggerListenersBeforeRules(rules, facts);
    doFire(rules, facts);
    triggerListenersAfterRules(rules, facts);
}

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;
            }
        }
    }
}

public final class InferenceRulesEngine extends AbstractRulesEngine

 说明:

  • 基于facts选择rules,并且根据他们priority属性的自然顺序触发
  • 这个实现持续地选择和触发规则,直到没有更多的规则可用为止

 代码关注点:fire()

Q1、引擎实现?---借助DefaultRulesEngine

public InferenceRulesEngine(RulesEngineParameters parameters) {
    super(parameters);
    delegate = new DefaultRulesEngine(parameters);
}

@Override
public void fire(Rules rules, Facts facts) {
    Set<Rule> selectedRules;
    do {
        LOGGER.debug("Selecting candidate rules based on the following facts: {}", facts);
        selectedRules = selectCandidates(rules, facts);
        if (!selectedRules.isEmpty()) {
            delegate.fire(new Rules(selectedRules), facts);
        } else {
            LOGGER.debug("No candidate rules found for facts: {}", facts);
        }
    } while (!selectedRules.isEmpty());
}

private Set<Rule> selectCandidates(Rules rules, Facts facts) {
    Set<Rule> candidates = new TreeSet<>();
    for (Rule rule : rules) {
        if (rule.evaluate(facts)) {
            candidates.add(rule);
        }
    }
    return candidates;
}

【注意】DefaultRulesEngine和InferenceRulesEngine都是final的,如果不适合,不能继承,只能继承AbstractRulesEngine,并重写。

c)       Rule实现:BasicRule与DefaultRule

  • BasicRule:提供公共方法的基础Rule,可以继承、重写
  • DefaultRule:BasicRule的子类,重写了BasicRule的evaluate、execute;注意该类访问修饰符是默认
  • Q:如何定义rule又不继承Rule或者BasicRule?----- 看RuleProxy实现

d)      ActionMethodOrderBean:关联操作方法及其执行顺序的实用程序类

e)      NoSuchFactException:RuntimeException子类

f)      RuleBuilder:Rule实例构建器

g)     RuleDefinitionValidator:此组件验证带注解的规则对象是否定义有效

h)     RuleProxy:用于从带注解的对象创建规则代理的主类

i)      Utils:生成代理类是注解解析工具类

core包UML

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值