推广

Java之规则引擎 Easy Rules

iseeyu2年前 (2024-02-22)推广137

在这里插入图片描述

2. 规则定义

2.1. 定义规则

大多数业务规则可以用以下定义表示:

Name : 一个命名空间下的唯一的规则名称
Description : 规则的简要描述
Priority : 相对于其他规则的优先级
Facts : 事实,可立即为要处理的数据
Conditions : 为了应用规则而必须满足的一组条件
Actions : 当条件满足时执行的一组动作
Easy Rules为每个关键点提供了一个抽象来定义业务规则。

在Easy Rules中,Rule接口代表规则

public interface Rule {

    /**
    * This method encapsulates the rule's conditions.
    * @return true if the rule should be applied given the provided facts, false otherwise
    */
    boolean evaluate(Facts facts);

    /**
    * This method encapsulates the rule's actions.
    * @throws Exception if an error occurs during actions performing
    */
    void execute(Facts facts) throws Exception;

    //Getters and setters for rule name, description and priority omitted.

}

evaluate方法封装了必须计算结果为TRUE才能触发规则的条件。execute方法封装了在满足规则条件时应该执行的动作。条件和操作由Condition和Action接口表示。

定义规则有两种方式:

通过在POJO类上添加注解
通过RuleBuilder API编程

可以在一个POJO类上添加@Rule注解,例如:

@Rule(name = "my rule", description = "my rule description", priority = 1)
public class MyRule {

    @Condition
    public boolean when(@Fact("fact") fact) {
        //my rule conditions
        return true;
    }

    @Action(order = 1)
    public void then(Facts facts) throws Exception {
        //my actions
    }

    @Action(order = 2)
    public void finally() throws Exception {
        //my final actions
    }

}

@Condition注解指定规则条件
@Fact注解指定参数
@Action注解指定规则执行的动作

RuleBuilder支持链式风格定义规则,例如:

Rule rule = new RuleBuilder()
                .name("myRule")
                .description("myRuleDescription")
                .priority(3)
                .when(condition)
                .then(action1)
                .then(action2)
                .build();

组合规则

CompositeRule由一组规则组成。这是一个典型地组合设计模式的实现。

组合规则是一个抽象概念,因为可以以不同方式触发组合规则。

Easy Rules自带三种CompositeRule实现:

UnitRuleGroup : 要么应用所有规则,要么不应用任何规则(AND逻辑)
ActivationRuleGroup : 它触发第一个适用规则,并忽略组中的其他规则(XOR逻辑)
ConditionalRuleGroup : 如果具有最高优先级的规则计算结果为true,则触发其余规则

复合规则可以从基本规则创建并注册为常规规则:

//Create a composite rule from two primitive rules
UnitRuleGroup myUnitRuleGroup = new UnitRuleGroup("myUnitRuleGroup", "unit of myRule1 and myRule2");
myUnitRuleGroup.addRule(myRule1);
myUnitRuleGroup.addRule(myRule2);

//Register the composite rule as a regular rule
Rules rules = new Rules();
rules.register(myUnitRuleGroup);

RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, someFacts);

每个规则都有优先级。它代表触发注册规则的默认顺序。默认情况下,较低的值表示较高的优先级。可以重写compareTo方法以提供自定义优先级策略。

2.2. 定义事实

在Easy Rules中,Fact API代表事实

public class Fact<T> {
     private final String name;
     private final T value;
}

在这里插入图片描述

举个栗子:

Fact<String> fact = new Fact("foo", "bar");
Facts facts = new Facts();
facts.add(fact);

或者,也可以用这样简写形式

Facts facts = new Facts();
facts.put("foo", "bar");

用@Fact注解可以将Facts注入到condition和action方法中

@Rule
class WeatherRule {

    @Condition
    public boolean itRains(@Fact("rain") boolean rain) {
        return rain;
    }

    @Action
    public void takeAnUmbrella(Facts facts) {
        System.out.println("It rains, take an umbrella!");
        // can add/remove/modify facts
    }

}

2.3. 定义规则引擎

Easy Rules提供两种RulesEngine接口实现:

DefaultRulesEngine : 根据规则的自然顺序应用规则
InferenceRulesEngine : 持续对已知事实应用规则,直到不再适用任何规则为止

创建规则引擎:

RulesEngine rulesEngine = new DefaultRulesEngine();

// or

RulesEngine rulesEngine = new InferenceRulesEngine();

然后,注册规则

rulesEngine.fire(rules, facts);

规则引擎有一些可配置的参数,如下图所示:

在这里插入图片描述

举个栗子:

RulesEngineParameters parameters = new RulesEngineParameters()
    .rulePriorityThreshold(10)
    .skipOnFirstAppliedRule(true)
    .skipOnFirstFailedRule(true)
    .skipOnFirstNonTriggeredRule(true);

RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

2.4. 定义规则监听器

通过实现RuleListener接口

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) { }

}

3. 示例

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cjs.example</groupId>
    <artifactId>easy-rules-quickstart</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-rules-core</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-rules-support</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-rules-mvel</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.30</version>
        </dependency>
    </dependencies>
</project>

在这里插入图片描述

4. 扩展

规则本质上是一个函数,如y=f(x1,x2,..,xn)

规则引擎就是为了解决业务代码和业务规则分离的引擎,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离。

还有一种常见的方式是Java+Groovy来实现,Java内嵌Groovy脚本引擎进行业务规则剥离。

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/55899.html

相关文章

逸仙电商旗下品牌完美日记多渠道运营

逸仙电商旗下品牌完美日记多渠道运营

供应链相关的布局之外,多样化的拓展同样成为过去一年完美日记发展最迅速的板块:淘系渠道上,完美日记已经连续多月蝉联天猫彩妆销售冠军,已经开出50多家线下店铺。目前,完美日记给出的官方显示,其全网粉丝已超2500万,月曝光量超十亿。完美日记母公司逸仙副总裁黄一耕去年曾向我们强调...

【4A营销广告圈】2022年6月营销策划案-194例

【4A广告圈】最新收录:2022年6月营销案-194例,以下为部分:20220623-乌镇蚁特营-楼书.pdf20220623-全国新房月报(4月)-58安居客房产研究院-2022.4-20页.pdf20220623-锐理-2022年4月份青岛房地产月度简报-72页.pdf...

我来教你网站策划推广浅谈(网站策划推广招聘)

我来教你网站策划推广浅谈(网站策划推广招聘)

上海有位朋友发来邮件,希望我能为他的推广出点主意,这是一个主要面向营销人的资讯网站,目前还只在策划中。面对不同行业,不同目标受众甚至不同地区具体的推广策略都是不同的。因此在不了解具体细节的情况下,我无法给出具体的推广建议,只能就商业网站推广的共性给他提一点建议。想到可能对其他朋友可能也有点帮助,就把...

SEM狙击战术|百度竞价推广营销实战指南(免费领取)

这本白皮书是通过对 SEM 商业行为的参与者:用户、商家、平台的需求的探究和行为的研究,梳理推导出来运营的基本方法,然后在此方法上,再根据 SEM 实际投放过程中会遇到的各种问题和广告主们的需求,总结迭代出来的性更强、目的性更强、收益更高的 SEM 投放方法论。“ 狙击战术...

系统默认好评计分吗(淘宝评价计分规则)

系统默认好评计分吗(淘宝评价计分规则)

  好评是不能删除和修改的,系统默认好评也是一样。如果在系统默认好评之后,我们使用了一段时间发现这个产品不好,还是可以写追评的哦。   我们在淘宝购买任意产品,收货后可以给这个产品写评价,如果超过时间没有写,系统将自动默认为好评。大多数消费者懒得评价,都是让系统默认好评的。不过,这种评价怎么修...

分享SEO优化之网页标题作弊与规范。

分享SEO优化之网页标题作弊与规范。

百度算法的不断更新也在不断的要求我们的一系列规范,接下来咱们就来说说关于作弊的行为和规范,·从而保证搜索用户体验,促进搜索生态良性发展。而好的网页标题,不仅能明确表达网页的主旨目的,更能给到搜索用户引导,吸引目标用户点击。 一、网页标题定义与作用 1、定义:网页标题是对一个网页的高度概...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片