Easy-Rules引擎

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

Easy-Rules规则引擎

使用情景:

​ 当代码需要多次进行if/else硬编码的时候,会导致代码的可读性大大降低,后期维护的成本增高。所以引入规则引擎,easy-rules是一个简单但是功能强大的规则引擎,提供了以下特性:

  • 轻量级框架和易学习的API
  • 基于POJO 的开发
  • 支持从原始规则进行规则的组合
  • 支持表达式(MVEL,SPEL和JEXL)定义规则

主要的接口:

​ Rules(规则接口),Facts(事实接口),RulesEngine(规则引擎接口)

快速开始

下面使用POJO 的方式进行示例

想了MVEL等方式定义的实例转到: https://segmentfault.com/a/1190000022939252

官方文档的GitHub地址:https://github.com/j-easy/easy-rules/wiki/defining-rules

1. 导入依赖

<!-- 导入此依赖只能使用注解形式进行规则创建及添加 -->
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>4.1.0</version>
</dependency>
<!--使用mvel和spel进行配置的时候需要导入的依赖-->
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-mvel</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-spel</artifactId>
    <version>3.4.0</version>
</dependency>

2. 规则编写

**规则一:**能被3整除的数

@Rule(name = "被3整除", description = "number如果被3整除,打印:number is three", priority = 1)
public class ThreeRule {
    /**
     * Condition:条件判断注解:如果return true, 执行Action
     * @param number
     */
    @Condition
    public boolean isThree(@Fact("number") int number) {
        return number % 3 == 0;
    }
 // Action 执行方法注解
    @Action
    public void threeAction(@Fact("number") int number) {
        System.out.println(number + " is three");
    }
}

**规则二:**能被8整除

@Rule(name = "被8整除", priority = 1)
public class EightRule {
    @Condition
    public boolean isEight(@Fact("number") int number) {
        return number % 8 == 0;
    }
    @Action
    public void eightAction(@Fact("number") int number) {
        System.out.println(number + " is eight");
    }
}

**组合规则:**既能被8整除又能被3整除

@Rule(name = "被3和8同时整除", description = "这是一个组合规则", priority = 0)
public class ThreeEightRuleUnitGroup extends UnitRuleGroup {
    // 传入其他规则进行组合
    public ThreeEightRuleUnitGroup(Object... rules) {
        for (Object rule : rules) {
            addRule(rule);
        }
    }
}

3. 初始化规则引擎,注册规则

class RulesTest {
    @Test
    public void test() {
        // 初始化规则引擎
        RulesEngineParameters parameters = new RulesEngineParameters()
                .skipOnFirstAppliedRule(true);
        DefaultRulesEngine engine = new DefaultRulesEngine(parameters);
        // 注册规则进入引擎
        Rules rules = new Rules();
        rules.register(new ThreeRule());
        rules.register(new EightRule());
        rules.register(new ThreeEightRuleUnitGroup(new ThreeRule(), new EightRule()));
        Facts facts = new Facts();
        facts.put("number", 24);
        // 开始判断
        engine.fire(rules, facts);
    }
}

Rule(规则)

可以把规则理解为if语句和满足条件后的执行体,当**@Condition注解的方法返回真的时候则执行@Action注解的**方法

1. Annotation

  • @Rule:写在Rule类上,标识这是一个规则,可选参数name(规则命名空间的唯一规则名称),description(描述规则的作用),priority(设置规则的优先级,值越优先级越高,不设置默认为**-1**,可以通过这个设置默认的响应规则
  • @Condition: 写在方法上作为判断条件,为真的时候返回True并执行**@Action方法,返回False**的时候则直接跳过

2. Rule定义

使用注解定义Rule

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

    @Condition
    public boolean when(@Fact("fact") fact) {
        // 规则条件
        return true;
    }
    @Action(order = 1)
    public void then(Facts facts) throws Exception {
        // 规则为true时的操作1
    }

    @Action(order = 2)
    public void finally() throws Exception {
        // 规则为true时的操作2
    }
}

使用RuleBuilder定义规则

Rule rule = new RuleBuilder()
                .name("myRule")
                .description("myRuleDescription")
                .priority(3)
                .when(condition) // condition是Condition接口的实例对象
                .then(action1) // action是Aciton接口的实例对象
                .then(action2)
                .build();

3. 组合规则

可以用前面基础的Rule规则自由组合一个更加复杂的规则

组合规则的分类

  • UnitRuleGroup: 是作为一个单元使用的组合规则,要么所有规则都应用,要么都不用
  • ActivationRuleGroup:激活规则组中触发第一个使用规则并忽略其他规则。规则首先按照在组中的自然顺序(默认情况下优先级)进行排序
  • ConditionalRuleGroup: 条件规则组将具有最高优先级的规则作为条件,如果具有最高优先级的规则的计算结果为true,那么将触发其余的规则

使用UnitRuleGroup定义

// 从两个原始规则创建组合规则
UnitRuleGroup myUnitRuleGroup =  new ThreeEightRuleUnitGroup("ThreeRule", "EightRule");

// 像常规规则一样注册组合规则
Rules rules = new Rules();
rules.register(myUnitRuleGroup);
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, someFacts);

// 定义的组合规则类
@Rule(name = "被3和8同时整除", description = "这是一个组合规则")
public class ThreeEightRuleUnitGroup extends UnitRuleGroup {

    public ThreeEightRuleUnitGroup(Object... rules) {
        for (Object rule : rules) {
            addRule(rule);
        }
    }

    @Override
    public int getPriority() {
        return 0;
    }

}

Facts(事实)

事实在我的理解就是为Rule规则提供类似反射一样的判断情况,如果没有Fact那么Rule的判断和普通的if/else没有区别,还是一种硬编码的判断。当加入了Facts的时候,我们可以自定义丰富的Fact事实去进行多元的判断,修改判断逻辑的时候可以不修改Rule就能实现

1. fact的组成

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

fact必须拥有两个值,一个名称和一个值。两个都不能为null,name代表的是事实的命名空间,会根据name发送给Rule中Fact相同的进行判断。value则可以携带判断信息和执行的方法。

**注:**可以自定义一个类,用来将判断的条件和判读后执行的方法都集成到里面去,减少代码的冗余

代码案例如下:

Facts facts = new Facts();
facts.put("wheather", "rain");  // 事实会被注入到对应的Rule中去

@Rule
class WeatherRule {
    @Condition
    public boolean itRains(@Fact("wheather") String wheather) {
        return "rain".equals(wheather);
    }
    @Action
    public void takeAnUmbrella(@Fact("wheather") String wheather) {
        System.out.println("It rains, take an umbrella!");
    }

}

注:

  • 如果条件方法中缺少注入的事实,引擎将记录一个警告,并认为条件被计算为false
  • 如果动作方法中缺少注入的事实,则不会执行该动作,并且抛出org.jeasy.rules.core.NoSuchFactException异常。

RulesEngine

进行规则和事实进行判断的启动入口

1. RulesEngine类型:

  • DefaultRulesEngine:根据规则的自然顺序(默认为优先级)应用规则。
  • InferenceRulesEngine:在已知的事实上不断地应用规则,直到没有更多的规则可用

2. 规则引擎的参数

参数 类型 默认值
rulePriorityThreshold int MaxInt
skipOnFirstAppliedRule boolean false
rulePriorityThreshold int false
skipOnFirstFailedRule boolean false
skipOnFirstNonTriggeredRule boolean false
  • skipOnFirstAppliedRule:当一个规则成功应用时,跳过余下的规则。
  • skipOnFirstFailedRule:当一个规则失败时,跳过余下的规则。
  • skipOnFirstNonTriggeredRule:当一个规则未触发时,跳过余下的规则。
  • rulePriorityThreshold:当优先级超过指定的阈值时,跳过余下的规则。

3. 规则引擎的创建

// 1.先设置规则引擎的参数RulesEngineParameters parameters = new RulesEngineParameters()
RulesEngineParameters parameters = new RulesEngineParameters()
        .rulePriorityThreshold(10)
        .skipOnFirstAppliedRule(true)
        .skipOnFirstFailedRule(true)
        .skipOnFirstNonTriggeredRule(true);

// 2. 将引擎参数添加到规则引擎中去,进行规则引擎的初始化
RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

Listener

1. 定义规则监听器

如果想对规则进行监听,需要自定义个一个类去实现这个接口然后注册到规则引擎当中去

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.
     */
    default void afterEvaluate(Rule rule, Facts facts, boolean evaluationResult) { }

    /**
     * Triggered on condition evaluation error due to any runtime exception.
     */
    default void onEvaluationError(Rule rule, Facts facts, Exception exception) { }

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

    /**
     * Triggered after a rule has been executed successfully.
     */
    default void onSuccess(Rule rule, Facts facts) { }

    /**
     * Triggered after a rule has failed.
     */
    default void onFailure(Rule rule, Facts facts, Exception exception) { }

}

2. 定义规则引擎监听器

public interface RulesEngineListener {
    /**
     * @param rules to fire
     * @param facts present before firing rules
     */
    default void beforeEvaluate(Rules rules, Facts facts) { }

    /**
     * @param rules fired
     * @param facts present after firing rules
     */
    default void afterExecute(Rules rules, Facts facts) { }
}

3. 使用例子

创建一个规则监听器的例子,规则引擎的类似文章来源地址https://www.toymoban.com/news/detail-770856.html

public class MyRuleListener implements RuleListener {
    @Override
    public boolean beforeEvaluate(Rule rule, Facts facts) {
        System.out.println(rule.getName() + "is going to evaluate !!");
        return true;
    }

    @Override
    public void beforeExecute(Rule rule, Facts facts) {
        System.out.println(rule.getName() + "is going to execute !");
    }
}

// 注册到规则引擎中去  
DefaultRulesEngine engine = new DefaultRulesEngine();
engine.registerRuleListener(new MyRuleListener());	

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

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

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

相关文章

  • Easy Rules规则引擎(2-细节篇)

    在 Easy Rules规则引擎(1-基础篇) 中我们已经简单介绍了 Easy Rules 规则引擎的使用示例,这节我们详解介绍一下规则引擎的相关参数配置实例还有组合规则。 Easy Rules 规则引擎支持下面参数配置: 参数名称 参数类型 必选 默认值 rulePriorityThreshold int 否 Integer.MAX_VALUE skipOnFirst

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

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

    2024年02月14日
    浏览(47)
  • Spring Boot 整合流程引擎 Flowable,so easy

    为啥想写 flowable 呢?原因很简单,因为最近在录的 tienchin 项目视频会用到,先写一篇文章和大家打打预防针,后面视频再细讲。 流程引擎,也算是一个比较常见的工具了,我们在日常的很多开发中都会用到,当然用的最多的就是 OA 系统了,但是在一些非 OA 系统中,我们也

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

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

    2024年02月15日
    浏览(55)
  • idea中Easy Code模版配置

    controller.java.vm模版 dao.java.vm模版 entity.java.vm模版 mapper.xml.vm模版 service.java.vm模版 serviceImpl.java.vm模版 语法规范

    2024年02月16日
    浏览(33)
  • Java轻量级全文检索引擎Lucene使用及优化

    Lucene是一个开源的全文检索引擎工具包由Doug Cutting编写。它被设计用于实现全文搜索功能,即读入一堆文本文件并将其转换为易于搜索的数据结构。Lucene提供了一组简单而强大的API,使得索引和搜索过程变得非常方便。 Lucene广泛应用于从1200万站点中进行互联网搜索等搜索引

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

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

    2024年01月17日
    浏览(90)
  • 【游戏引擎Easy2D】学C++还在面对黑框框?那是你没看这篇文,游戏引擎教会你

      🧛‍♂️ iecne个人主页: 点赞关注收藏评论支持哦~ 💡每天 关注 iecne的作品,一起进步 ✨一起学习内容 专栏 :C++保姆级入门教程  C++每日一题  C++游戏设计教程 👉本文收录 专栏 :C++游戏引擎教程与实战 🐳希望大家多多支持🥰一起进步呀!   目录 ✨前言 坐标系和

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

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

    2024年01月25日
    浏览(51)
  • Java项目——文档搜索引擎

    实现一个较为简单的搜索引擎,在拥有较多网页的基础上,在用户输入查询词之后,能够从这些网页中尽可能地匹配出用户想要的网页 当然,不同于百度搜狗这种搜索引擎,它们能够对互联网中大量的网站都进行搜索,我们这里实现的是针对「Java 文档」的搜索引擎,就像下

    2024年02月02日
    浏览(42)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包