likes
comments
collection
share

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

作者站长头像
站长
· 阅读数 10

规则引擎是什么

规则引擎是一种基于规则的软件系统,它可以自动化地执行规则,从而实现业务流程控制、风险管理、决策支持等功能。规则引擎通常由三个主要组件组成:规则信息库、逻辑推理引擎和执行引擎。 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

规则信息库

规则信息库是规则引擎的数据核心,它包含了所有的规则。

规则可以是 业务规则决策规则计算规则 等等。规则信息库通常采用类似于数据库的结构来存储规则,每个规则都有一个唯一的标识符、一个条件部分和一个结果部分。

  • 条件部分描述了规则的前提条件
  • 结果部分描述了规则的执行结果

逻辑推理引擎

逻辑推理引擎是规则引擎的计算核心,它负责根据规则信息库中的规则和输入数据来推导出结果。

逻辑推理引擎通常采用基于规则的推理机制,即根据规则的前提条件和输入数据来匹配规则,并执行规则的结果部分。

推理引擎还可以支持多种推理算法,如前向推理、后向推理、混合推理等。

程序执行引擎

程序执行引擎是规则引擎的执行核心,它负责将推理引擎计算出的结果应用到实际业务中。

程序执行引擎通常采用类似于工作流引擎的方式来执行规则,即按照规则的执行顺序来依次执行规则组件。程序执行引擎还可以支持多种执行方式,如同步执行、异步执行、批量执行、延时执行或者定时执行等。

程序执行引擎的优点在于它可以将 业务规则计算逻辑 从应用程序中分离出来,从而实现 业务逻辑可配置可扩展可重用 。程序执行引擎还可以提高业务流程的自动化程度,减少人工干预,提高业务处理效率和准确性。

总之,规则引擎是一种强大的软件工具,它可以帮助企业实现业务流程控制、风险管理、决策支持等功能,提高业务处理效率和准确性

规则引擎的使用场景

当然可以,请问您需要的规则引擎是用于什么样的场景和目的呢?例如,是用于业务流程控制、风险管理、决策支持等方面。同时,您需要考虑的因素还包括规则的复杂度、数据量、性能要求等等。


规则引擎的核心逻辑模型的介绍

以下是规则引擎的核心逻辑模型的大概架构图,如下所示: 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计) 接下来我们,针对于Rule规则模型以及RuleEngine运作引擎模型的大概行为以及服务能力进行相关的介绍和说明。

Rule规则模型

Rule规则模型属于规则引擎中最基础的数据信息模型,同样也是整个规则引擎执行逻辑的“物质基础”,它为程序执行引擎和逻辑推理引擎提供了根本方向。它主要由三部分组成: 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

Action- 触发行为

Action(触发行为)主要表示为执行某种行为或者操作的模式,大家可以理解为执行处理的一个操作。例如:当我们发觉我们饿了,我们就应该去吃饭,而这里的“吃饭”代表着就是Action行为操作。至于吃什么,就如同我们的参数一样,传递苹果我们就吃苹果;传递香蕉,我们就吃香蕉。

代码案例

下面我们代码去实现一个Action触发的接口模型,其中Action触发行为的视实现,只有通过

@FunctionalInterface
public interface Action {
    void execute(Facts facts) throws Exception;
}

从以上代码可以看出,该代码段主要代表了值的执行行为和内容。其中,它的参数类型为Facts。Facts是用户可以自定义的事实,它表示实际的参数,也可以称为事实参数(Fact Parameters)。关于Facts的具体内容,我们将在后面的参数部分进行介绍,目前暂时不进行过多赘述。

大家只要知道Action接口主要用于定义我们的执行行为就可以了,当规则的条件评估为 "true "时执行操作。

Condition-条件判断

Condition的条件接口,主要用于控制和判断是否要执行上面所定义的Action接口所要执行的行为动作,通过evaluate方法的返回值,从而判断是否需要进行执行Action接口的实际功能。下面则是我们定义的Condtion条件判断接口的执行逻辑代码。

@FunctionalInterface
public interface Condition {

    /**
     * Evaluate the condition according to the known facts.
     * @param facts known when evaluating the rule.
     * @return true if the rule should be triggered, false otherwise
     */
    boolean evaluate(Facts facts);
    /**
     * A NoOp {@link Condition} that always returns false.
     */
    Condition FALSE = facts -> false;

    /**
     * A NoOp {@link Condition} that always returns true.
     */
    Condition TRUE = facts -> true;
}

其中这两个字段,主要用于Lamda表达式作为一个变量处理。因为属于Lamda表达式,所以不会立刻加载,属于懒惰操作加载处理。

  /**
     * A NoOp {@link Condition} that always returns false.
     */
    Condition FALSE = facts -> false;

    /**
     * A NoOp {@link Condition} that always returns true.
     */
    Condition TRUE = facts -> true;

从对于Condition接口的定义的evaluate(Facts facts);方法,可以看出来,它的参数也是Facts。因此可以的得出结论,Condition也是根据实际情况的参数进行判断是否符合满足条件进行执行对应的Condition条件。

Parameter-实际参数

首先Parameter的实际参数模型,主要属于一个抽象、泛化的类型数据模型,最简单也最方便的数据模型就是Map数据模型。但是由于Map的性能以及一些定制化功能的开发量过多,所以我们再次没有选择Map,而是选择了自定义K-V结构化的数据模型。

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

Fact的参数模型

当涉及到Fact数据模型子元素时,它通常采用键-值(K-V)结构。这种结构由两部分组成:键(Key)和对应的值(Value)。键用于标识和索引数据,而值则包含了与该键相关联的具体信息。

Fact数据模型子元素的关键特点是它们的多样性和可扩展性。通过使用K-V结构,我们可以根据实际需求存储和表达各种类型的数据。例如,对于一个商品,可以使用键值对来表示商品的名称、价格、描述等信息。

另一个重要的特征是Fact的可组合性。多个Fact数据模型子元素可以组合成一个更复杂的数据集合。这种组合性使得我们能够处理和管理大量的数据,并在需要时对其进行灵活的访问和操作。

总结一下,Fact数据模型子元素是基于K-V结构的,用于存储和表示各种类型数据的元素。它们具有多样性、可扩展性和可组合性的特点,使我们能够有效地处理和管理复杂的数据集合。

代码案例
public class Fact<T> {


	private final String name;

	private final T value;

	/**
	 * Create a new fact.
	 * @param name of the fact
	 * @param value of the fact
	 */
	public Fact(String name, T value) {
		Objects.requireNonNull(name, "name must not be null");
		Objects.requireNonNull(value, "value must not be null");
		this.name = name;
		this.value = value;
	}

	/**
	 * Get the fact name.
	 * @return fact name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Get the fact value.
	 * @return fact value
	 */
	public T getValue() {
		return value;
	}

	@Override
	public String toString() {
		return "Fact{" +
				"name='" + name + '\'' +
				", value=" + value +
				'}';
	}

	/*
	 * The Facts API represents a namespace for facts where each fact has a unique name.
	 * Hence, equals/hashcode are deliberately calculated only on the fact name.
	 */
	
	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		Fact<?> fact = (Fact<?>) o;
		return name.equals(fact.name);
	}

	@Override
	public int hashCode() {
		return Objects.hash(name);
	}
}
Facts的参数模型

在这种情况下,参数主要由Fact数据模型子元素(K-V结构)和K-V结构体集合组成。实际过程中可能会有多个K-V对应的数据需要传输,因此需要使用另一个容器来组装参数数据集合模型,即Facts。Facts表示多个Fact,即多个K-V结构的数据集合。

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

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

    /**
     * Add a fact, replacing any fact with the same name.
     *
     * @param name of the fact to add, must not be null
     * @param value of the fact to add, must not be null
     */
    public <T> void put(String name, T value) {
        Objects.requireNonNull(name, "fact name must not be null");
        Objects.requireNonNull(value, "fact value must not be null");
        Fact<?> retrievedFact = getFact(name);
        if (retrievedFact != null) {
            remove(retrievedFact);
        }
        add(new Fact<>(name, value));
    }
    
    /**
     * Add a fact, replacing any fact with the same name.
     * 
     * @param fact to add, must not be null
     */
    public <T> void add(Fact<T> fact) {
        Objects.requireNonNull(fact, "fact must not be null");
        Fact<?> retrievedFact = getFact(fact.getName());
        if (retrievedFact != null) {
            remove(retrievedFact);
        }
        facts.add(fact);
    }

    /**
     * Remove a fact by name.
     *
     * @param factName name of the fact to remove, must not be null
     */
    public void remove(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        Fact<?> fact = getFact(factName);
        if (fact != null) {
            remove(fact);
        }
    }

    /**
     * Remove a fact.
     *
     * @param fact to remove, must not be null
     */
    public <T> void remove(Fact<T> fact) {
        Objects.requireNonNull(fact, "fact must not be null");
        facts.remove(fact);
    }

    /**
     * Get the value of a fact by its name. This is a convenience method provided
     * as a short version of {@code getFact(factName).getValue()}.
     *
     * @param factName name of the fact, must not be null
     * @param <T> type of the fact's value
     * @return the value of the fact having the given name, or null if there is
     * no fact with the given name
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        Fact<?> fact = getFact(factName);
        if (fact != null) {
            return (T) fact.getValue();
        }
        return null;
    }
    
    /**
     * Get a fact by name.
     *
     * @param factName name of the fact, must not be null
     * @return the fact having the given name, or null if there is no fact with the given name
     */
    public Fact<?> getFact(String factName) {
        Objects.requireNonNull(factName, "fact name must not be null");
        return facts.stream()
                .filter(fact -> fact.getName().equals(factName))
                .findFirst()
                .orElse(null);
    }

    /**
     * Return a copy of the facts as a map. It is not intended to manipulate
     * facts outside of the rules engine (aka other than manipulating them through rules).
     *
     * @return a copy of the current facts as a {@link HashMap}
     */
    public Map<String, Object> asMap() {
        Map<String, Object> map = new HashMap<>();
        for (Fact<?> fact : facts) {
            map.put(fact.getName(), fact.getValue());
        }
        return map;
    }

    /**
     * Return an iterator on the set of facts. It is not intended to remove
     * facts using this iterator outside of the rules engine (aka other than doing it through rules)
     * 
     * @return an iterator on the set of facts
     */
    @Override
    public Iterator<Fact<?>> iterator() {
        return facts.iterator();
    }

    /**
     * Clear facts.
     */
    public void clear() {
        facts.clear();
    }

    @Override
    public String toString() {
        Iterator<Fact<?>> iterator = facts.iterator();
        StringBuilder stringBuilder = new StringBuilder("[");
        while (iterator.hasNext()) {
            stringBuilder.append(iterator.next().toString());
            if (iterator.hasNext()) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

当看到Facts的源码时,可以发现它与线程池的Executors组件相似。事实上,Facts可以被看作是一个类似工厂方法的组件,它帮助我们维护内部的Fact集合,并提供了对这些Fact数据集合进行增加、删除、更新和查询(CRUD操作)的能力。不仅如此,Facts还能提供其他辅助方法来处理这些内部数据集合。通过使用Facts数据模型,我们能够更加高效地管理和操作数据集合。

Rule逻辑模型

规则是可以被规则引擎触发的抽象概念。规则需要在规则类型的命名空间中进行注册,并且每个规则必须具有唯一的名称。这样的设计使得规则引擎能够准确地识别和触发特定的规则。通过将规则注册到适当的命名空间中,并提供唯一的名称,我们能够确保规则的正确性和可靠性。这种规则抽象和命名约定的使用,使规则引擎的操作变得更加灵活和可维护。

Rule逻辑模型属性

Rule的逻辑模型的属性主要由规则名称、规则描述和规则的优先级三部分进行组成介绍。他们分别定义了规则的命名值,主要用于区分每个rule之间的唯一性以及对应的规则含义、多个规则之间的优先级。当然每一个属性都有自己的优先级。 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

Rule代码案例
public interface Rule extends Comparable<Rule> {

    /**
     * Default rule name.
     */
    String DEFAULT_NAME = "rule";

    /**
     * Default rule description.
     */
    String DEFAULT_DESCRIPTION = "description";

    /**
     * Default rule priority.
     */
    int DEFAULT_PRIORITY = Integer.MAX_VALUE - 1;

    /**
     * Getter for rule name.
     * @return the rule name
     */
    default String getName() {
        return DEFAULT_NAME;
    }

    /**
     * Getter for rule description.
     * @return rule description
     */
    default String getDescription() {
        return DEFAULT_DESCRIPTION;
    }

    /**
     * Getter for rule priority.
     * @return rule priority
     */
    default int getPriority() {
        return DEFAULT_PRIORITY;
    }

    /**
     * This method implements the rule's condition(s).
     * <strong>Implementations should handle any runtime exception and return true/false accordingly</strong>
     *
     * @return true if the rule should be applied given the provided facts, false otherwise
     */
    boolean evaluate(Facts facts);

    /**
     * This method implements the rule's action(s).
     * @throws Exception thrown if an exception occurs when performing action(s)
     */
    void execute(Facts facts) throws Exception;
}

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

Rule的规则行为

方法boolean evaluate(Facts facts);主要用于代理与对应的Condition接口进行交互,从而处理和控制条件判断的走向。然而,需要注意的是,Rule类本身是一个门面操作,实际调用的方法属于Condition接口的具体实现类。类似地,void execute(Facts facts) throws Exception;方法对应的是Action接口的方法。

这种设计模式允许Rule类作为一个中间层,将调用委托给具体的Condition和Action实现类,从而实现了更好的解耦。通过这种抽象和代理模式的应用,我们能够更加灵活地处理和控制条件判断和操作的逻辑。

Rules的工厂类操作

与Fact类似,Rule也有一个相似的Rules工厂类。这个工厂类是一个类型工厂集合,用于存储Rule对象的模型集合数据。它可以容纳多个规则信息,因为在条件流转的过程中,通常会存在多个规则模型,而不仅仅是一个。

通过使用这个Rules工厂类,我们可以方便地管理和操作Rule对象。它允许我们动态地添加、修改和删除规则,从而实现更灵活的条件流转控制。

代码案例
public class Rules implements Iterable<Rule> {

    private Set<Rule> rules = new TreeSet<>();

    /**
     * Create a new {@link Rules} object.
     *
     * @param rules to register
     */
    public Rules(Set<Rule> rules) {
        this.rules = new TreeSet<>(rules);
    }

    /**
     * Create a new {@link Rules} object.
     *
     * @param rules to register
     */
    public Rules(Rule... rules) {
        Collections.addAll(this.rules, rules);
    }

    /**
     * Create a new {@link Rules} object.
     *
     * @param rules to register
     */
    public Rules(Object... rules) {
        this.register(rules);
    }

    /**
     * Register one or more new rules.
     *
     * @param rules to register, must not be null
     */
    public void register(Object... rules) {
        Objects.requireNonNull(rules);
        for (Object rule : rules) {
            Objects.requireNonNull(rule);
            this.rules.add(RuleProxy.asRule(rule));
        }
    }

    /**
     * Unregister one or more rules.
     *
     * @param rules to unregister, must not be null
     */
    public void unregister(Object... rules) {
        Objects.requireNonNull(rules);
        for (Object rule : rules) {
            Objects.requireNonNull(rule);
            this.rules.remove(RuleProxy.asRule(rule));
        }
    }

    /**
     * Unregister a rule by name.
     *
     * @param ruleName name of the rule to unregister, must not be null
     */
    public void unregister(final String ruleName) {
        Objects.requireNonNull(ruleName);
        Rule rule = findRuleByName(ruleName);
        if (rule != null) {
            unregister(rule);
        }
    }

    /**
     * Check if the rule set is empty.
     *
     * @return true if the rule set is empty, false otherwise
     */
    public boolean isEmpty() {
        return rules.isEmpty();
    }

    /**
     * Clear rules.
     */
    public void clear() {
        rules.clear();
    }

    /**
     * Return how many rules are currently registered.
     *
     * @return the number of rules currently registered
     */
    public int size() {
        return rules.size();
    }

    /**
     * Return an iterator on the rules set. It is not intended to remove rules
     * using this iterator.
     * @return an iterator on the rules set
     */
    @Override
    public Iterator<Rule> iterator() {
        return rules.iterator();
    }

    private Rule findRuleByName(String ruleName) {
        return rules.stream()
                .filter(rule -> rule.getName().equalsIgnoreCase(ruleName))
                .findFirst()
                .orElse(null);
    }
}
运作流程模式

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计) 首先,在执行一个Rule规则模型时,它会经过Condition接口的执行。在这个步骤中,该规则会执行evaluate方法来判断条件是否满足。如果条件判断结果为true,接下来将执行Action操作,从而控制规则的处理模式。在整个过程中,Fact实际参数模型起着关键作用,它主要用于传输数据信息到各个执行路径节点。

RuleListener

RuleListener是规则执行事件的监听器,主要用于监控每个执行单元节点的执行前后Hook的AOP拦截作用,它也是主要面向于Action接口的实现方法以及Condition的实现方法,方便我们实时以及动态的审计方面进行控制我们的规则引擎的处理模式和实现方式。

Condition的审计操作

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

  • beforeEvaluate:在评估规则前触发。
  • afterEvaluate:在评估规则后触发。
  • onEvaluationError:运行时异常导致条件评估错误时触发。
Action的审计操作

【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计)

代码案例
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) { }

}

规则引擎RuleEngine

RuleEngine属于整个规则引擎的总体门面接口类,它主要用于操作整体的规则引擎的总体操作入口。 【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(逻辑模型和API设计) 首先,针对于RuleEngine属于一个接口,他主要定义不同种类的规则引擎的抽象定义结构。它主要分为三个部分:RuleEngineListener-规则执行监听器,它主要作为做维护和规则引擎层面的控制监听器,获取和处理对应的RuleEngineParameter-规则引擎参数,它主要用于处理规则引擎参数将引擎级别参数进行控制对应的规则执行流程,从而进行控制对应的规则处理模式。

RuleEngineListener

该监听器与RuleListener不同,主要用于规则引擎级别的操作处理机制。它的主要作用是处理所有规则的操作,而对应的RuleListener负责处理规则内部的条件和动作操作的审计。

代码案例

public interface RulesEngineListener {

    /**
     * Triggered before evaluating the rule set.
     * <strong>When this listener is used with a {@link InferenceRulesEngine},
     * this method will be triggered before the evaluation of each candidate rule
     * set in each iteration.</strong>
     *
     * @param rules to fire
     * @param facts present before firing rules
     */
    default void beforeEvaluate(Rules rules, Facts facts) { }

    /**
     * Triggered after executing the rule set
     * <strong>When this listener is used with a {@link InferenceRulesEngine},
     * this method will be triggered after the execution of each candidate rule
     * set in each iteration.</strong>
     *
     * @param rules fired
     * @param facts present after firing rules
     */
    default void afterExecute(Rules rules, Facts facts) { }
}
  • beforeEvaluate:在评估规则集之前触发。当与默认的 RulesEngine 一起使用时,该方法将在每次迭代中在评估每个候选规则集之前触发。

  • afterExecute:在执行规则集后触发。当此监听器与默认规则引擎一起使用时,在每次迭代中执行完每个候选规则集后都会触发此方法。

代码案例

public interface RulesEngine {

    /**
     * Return the rules engine parameters.
     *
     * @return The rules engine parameters
     */
    RulesEngineParameters getParameters();

    /**
     * Return the list of registered rule listeners.
     *
     * @return the list of registered rule listeners
     */
    default List<RuleListener> getRuleListeners() {
        return Collections.emptyList();
    }

    /**
     * Return the list of registered rules engine listeners.
     *
     * @return the list of registered rules engine listeners
     */
    default List<RulesEngineListener> getRulesEngineListeners() {
        return Collections.emptyList();
    }

    /**
     * Fire all registered rules on given facts.
     */
    void fire(Rules rules, Facts facts);

    /**
     * Check rules without firing them.
     * @return a map with the result of evaluation of each rule
     */
    default Map<Rule, Boolean> check(Rules rules, Facts facts) {
        return Collections.emptyMap();
    }
}

RulesEngineParameters

RulesEngineParameters的参数模型主要用于以下的几种类型:

  • skipOnFirstAppliedRule:应用规则时跳过下一条适用规则的参数。
  • skipOnFirstNonTriggeredRule:当某条规则未触发时,跳过下一条适用规则的参数
  • skipOnFirstFailedRule:当一条规则失效时,跳过下一条适用规则的参数。
  • priorityThreshold: 如果优先级超过用户定义的阈值,则跳过下一条规则的参数。
public class RulesEngineParameters {

    /**
     * Default rule priority threshold.
     */
    public static final int DEFAULT_RULE_PRIORITY_THRESHOLD = Integer.MAX_VALUE;
    
    /**
     * Parameter to skip next applicable rules when a rule is applied.
     */
    private boolean skipOnFirstAppliedRule;

    /**
     * Parameter to skip next applicable rules when a rule is non triggered
     */
    private boolean skipOnFirstNonTriggeredRule;

    /**
     * Parameter to skip next applicable rules when a rule has failed.
     */
    private boolean skipOnFirstFailedRule;

    /**
     * Parameter to skip next rules if priority exceeds a user defined threshold.
     */
    private int priorityThreshold;

    /**
     * Create a new {@link RulesEngineParameters} with default values.
     */
    public RulesEngineParameters() {
        this.priorityThreshold = RulesEngineParameters.DEFAULT_RULE_PRIORITY_THRESHOLD;
    }

    /**
     * Create a new {@link RulesEngineParameters}.
     *
     * @param skipOnFirstAppliedRule parameter to skip next applicable rules on first applied rule.
     * @param skipOnFirstFailedRule parameter to skip next applicable rules on first failed rule.
     * @param skipOnFirstNonTriggeredRule parameter to skip next applicable rules on first non triggered rule.
     * @param priorityThreshold threshold after which rules should be skipped.
     */
    public RulesEngineParameters(final boolean skipOnFirstAppliedRule, final boolean skipOnFirstFailedRule, final boolean skipOnFirstNonTriggeredRule, final int priorityThreshold) {
        this.skipOnFirstAppliedRule = skipOnFirstAppliedRule;
        this.skipOnFirstFailedRule = skipOnFirstFailedRule;
        this.skipOnFirstNonTriggeredRule = skipOnFirstNonTriggeredRule;
        this.priorityThreshold = priorityThreshold;
    }

    public int getPriorityThreshold() {
        return priorityThreshold;
    }

    public void setPriorityThreshold(final int priorityThreshold) {
        this.priorityThreshold = priorityThreshold;
    }

    public RulesEngineParameters priorityThreshold(final int priorityThreshold) {
        setPriorityThreshold(priorityThreshold);
        return this;
    }

    public boolean isSkipOnFirstAppliedRule() {
        return skipOnFirstAppliedRule;
    }

    public void setSkipOnFirstAppliedRule(final boolean skipOnFirstAppliedRule) {
        this.skipOnFirstAppliedRule = skipOnFirstAppliedRule;
    }

    public RulesEngineParameters skipOnFirstAppliedRule(final boolean skipOnFirstAppliedRule) {
        setSkipOnFirstAppliedRule(skipOnFirstAppliedRule);
        return this;
    }

    public boolean isSkipOnFirstNonTriggeredRule() {
        return skipOnFirstNonTriggeredRule;
    }

    public void setSkipOnFirstNonTriggeredRule(final boolean skipOnFirstNonTriggeredRule) {
        this.skipOnFirstNonTriggeredRule = skipOnFirstNonTriggeredRule;
    }

    public RulesEngineParameters skipOnFirstNonTriggeredRule(final boolean skipOnFirstNonTriggeredRule) {
        setSkipOnFirstNonTriggeredRule(skipOnFirstNonTriggeredRule);
        return this;
    }

    public boolean isSkipOnFirstFailedRule() {
        return skipOnFirstFailedRule;
    }

    public void setSkipOnFirstFailedRule(final boolean skipOnFirstFailedRule) {
        this.skipOnFirstFailedRule = skipOnFirstFailedRule;
    }

    public RulesEngineParameters skipOnFirstFailedRule(final boolean skipOnFirstFailedRule) {
        setSkipOnFirstFailedRule(skipOnFirstFailedRule);
        return this;
    }

    @Override
    public String toString() {
        return "Engine parameters { " +
                "skipOnFirstAppliedRule = " + skipOnFirstAppliedRule +
                ", skipOnFirstNonTriggeredRule = " + skipOnFirstNonTriggeredRule +
                ", skipOnFirstFailedRule = " + skipOnFirstFailedRule +
                ", priorityThreshold = " + priorityThreshold +
                " }";
    }
}

fire触发操作入口

EasyRule是一个规则引擎库,它提供了一种方便的方法来处理规则和事实的关联。在EasyRule中,fire(Rules rules, Facts facts)是一个方法,用于触发并执行一组规则。

void fire(Rules rules, Facts facts);

这个方法需要两个参数:

  • rules:规则集合,它包含了需要执行的规则。
  • facts:事实集合,它包含了给定的事实,这些事实将被用于匹配规则的条件。

当调用fire(Rules rules, Facts facts)方法时,规则引擎会对每个规则进行逐个匹配。如果某个规则的条件能够与给定的事实相匹配,那么该规则的操作将被执行。

换句话说,fire(Rules rules, Facts facts)方法将根据给定的事实启动所有符合条件的规则,以便执行规则中定义的操作。

下节预告

接下来,我们会进行介绍和说明对应的“【底层服务/编程功底系列】「手把手教学系列」带你打造一个属于自己的规则引擎服务,打破任何业务难题(核心层实现设计)”,敬请期待。