我们在写业务代码经常遇到需要一大堆if/else,会导致代码可读性大大降低,有没有一种方法可以避免代码中出现大量的判断语句呢?

答案是用规则引擎,但是传统的规则引擎都比较重,比如开源的Drools,不适合在小需求中应用。最近在github上面看到一个傻瓜式的Java规则引擎Easy-Rules,这里结合自己写的demo介绍如何使用这个规则引擎,希望对大家有所帮助。

easy-rules的特点

1 轻量级类库和容易上手
2 基于POJO的开发与注解的编程模型
3 基于MVEL表达式的编程模型(适用于极简单的规则,一般不推荐)
4 支持根据简单的规则创建组合规则
5 方便且适用于java的抽象的业务模型规则

特点

概念

了解规则引擎,我们先了解几个概念,如图所示

我们看到

1)facts表示当前被传入的key:value结构的参数

2)rule就是一整个规则

3)Condition就是rule的判断条件

4)action就是满足Condition以后需要触发的动作

那么整个逻辑就是,当一个facts参数对象传入的时候,遍历rules各个规则。每个规则进行规则的条件判断,如果满足条件,那么就触发执行相应的业务逻辑。

其实总体逻辑依旧是一种类似if/else的概念

它主要包括几个主要的类或接口:Rule,RulesEngine,RuleListener,Facts

还有几个主要的注解:@Action,@Condition,@Fact,@Priority,@Rule

maven依赖

 1    <dependency>
2 <groupId>org.jeasy</groupId>
3 <artifactId>easy-rules-core</artifactId>
4 <version>3.3.0</version>
5 </dependency>
6 <dependency>
7 <groupId>org.jeasy</groupId>
8 <artifactId>easy-rules-mvel</artifactId>
9 <version>3.3.0</version>
10 </dependency>

maven

easy-rules的实现方式(2种)

  1. 实现Rule接口,并实现其evaluate和execute方法。
  2. 使用@Rule注解修饰POJO

实战

例1:基于POJO开发与注解的编程模型:判断1-50中,被3或者8整除的数

 编写规则POJO:

 1 @Rule(name = "被3整除", description = "number如果被3整除,打印:number is three")
2 public class ThreeRule {
3 /**
4 * Condition:条件判断注解:如果return true, 执行Action
5 *
6 * @param number
7 * @return
8 */
9 @Condition
10 public boolean isThree(@Fact("number") int number) {
11 return number % 3 == 0;
12 }
13
14 /**
15 * Action 执行方法注解
16 *
17 * @param number
18 */
19 @Action
20 public void threeAction(@Fact("number") int number) {
21 System.out.println(number + " is three");
22 }
23
24 /**
25 * Priority:优先级注解:return 数值越小,优先级越高
26 *
27 * @return
28 */
29 @Priority
30 public int getPriority() {
31 return 1;
32 }
33 }

规则1--被3整除

 1 @Rule(name = "被8整除")
2 public class EightRule {
3
4 /**
5 * 条件
6 *
7 * @param number
8 * @return
9 */
10 @Condition
11 public boolean isEight(@Fact("number") int number) {
12 return number % 8 == 0;
13 }
14
15 /**
16 * 满足条件的动作
17 *
18 * @param number
19 */
20 @Action
21 public void eightAction(@Fact("number") int number) {
22 System.out.println(number + " is eight");
23 }
24
25 /**
26 * 条件判断的优先级
27 *
28 * @return
29 */
30 @Priority
31 public int getPriority() {
32 return 2;
33 }
34 }

规则2--被8整除

 1 @Rule(name = "被3和8同时整除", description = "这是一个组合规则")
2 public class ThreeEightRuleUnitGroup extends UnitRuleGroup {
3
4 public ThreeEightRuleUnitGroup(Object... rules) {
5 for (Object rule : rules) {
6 addRule(rule);
7 }
8 }
9
10 @Override
11 public int getPriority() {
12 return 0;
13 }
14 }

规则3--被3和8同时整除

 1 @Rule(name = "既不被3整除也不被8整除", description = "打印number自己")
2 public class OtherRule {
3 @Condition
4 public boolean isOther(@Fact("number") int number){
5 return number % 3 != 0 || number % 8 != 0;
6 }
7
8 @Action
9 public void printSelf(@Fact("number") int number){
10 System.out.print(number);
11 }
12
13 @Priority
14 public int getPriority(){
15 return 3;
16 }
17 }

规则4--既不被3整除也不被8整除

 1 public class ThreeEightRuleLauncher {
2
3 public static void main(String[] args) {
4 /**
5 * 创建规则执行引擎
6 * 注意: skipOnFirstAppliedRule意思是,只要匹配到第一条规则就跳过后面规则匹配
7 */
8 RulesEngineParameters parameters = new
9 RulesEngineParameters().skipOnFirstAppliedRule(true);
10 RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
11 //创建规则
12 Rules rules = new Rules();
13 rules.register(new EightRule());
14 rules.register(new ThreeRule());
15 rules.register(new ThreeEightRuleUnitGroup(new EightRule(), new ThreeRule()));
16 rules.register(new OtherRule());
17 Facts facts = new Facts();
18 for (int i=1 ; i<=50 ; i++){
19 //规则因素,对应的name,要和规则里面的@Fact 一致
20 facts.put("number", i);
21 //执行规则
22 rulesEngine.fire(rules, facts);
23 System.out.println();
24 }
25 }
26 }

执行规则

例2:基于MVEL表达式的编程模型

本例演示如何使用MVEL表达式定义规则,MVEL通过Easy-Rules MVEL模块提供。此模块包含使用MVEL定义规则的API。我们将在这里使用这些API,其目标是实现一个简单的商店应用程序,要求如下:禁止儿童购买酒精,成年人的最低法定年龄为18岁。 商店顾客由Person类定义:

 1 @Data
2 @AllArgsConstructor
3 @NoArgsConstructor
4 public class Person {
5 private String name;
6
7 private boolean adult;
8
9 private int age;
10 //getter, setter 省略
11
12
13 public Person(String name, int age) {
14 this.name = name;
15 this.age = age;
16 }

Person

我们定义两个规则:

  • 规则1:可以更新Person实例,判断年龄是否大于18岁,并设置成人标志。
  • 规则2:判断此人是否为成年人,并拒绝儿童(即非成年人)购买酒精。

显然,规则1的优先级要大于规则2,我们可以设置规则1的Priority为1,规则2的Priority为2,这样保证规则引擎在执行规则的时候,按优先级的顺序执行规则。

 Rule ageRule = new MVELRule()
.name("age rule")
.description("Check if person"s age is > 18 and marks the person as adult")
.priority(1)
.when("person.age > 18")
.then("person.setAdult(true);");

规则1

1 规则2的定义,我们放到alcohol-rule.yml文件中
2
3 name: "alcohol rule"
4 description: "children are not allowed to buy alcohol"
5 priority: 2
6 condition: "person.isAdult() == false"
7 actions:
8 - "System.out.println("Shop: Sorry, you are not allowed to buy alcohol");"

规则2

 1 public class ShopLauncher {
2 public static void main(String[] args) throws Exception {
3 //创建一个Person实例(Fact)
4 Person tom = new Person("Tom", 19);
5 Facts facts = new Facts();
6 facts.put("person", tom);
7
8 //创建规则1
9 Rule ageRule = new MVELRule()
10 .name("age rule")
11 .description("Check if person"s age is > 18 and marks the person as adult")
12 .priority(1)
13 .when("person.age > 18")
14 .then("person.setAdult(true);");
15 //创建规则2
16 Rule alcoholRule = new MVELRuleFactory(new YamlRuleDefinitionReader()).
17 createRule(new FileReader(ResourceUtils.getFile("classpath:alcohol-rule.yml")));
18
19 Rules rules = new Rules();
20 rules.register(ageRule);
21 rules.register(alcoholRule);
22
23 //创建规则执行引擎,并执行规则
24 RulesEngine rulesEngine = new DefaultRulesEngine();
25 System.out.println("Tom: Hi! can I have some Vodka please?");
26 rulesEngine.fire(rules, facts);
27 System.out.println(JSON.toJSONString(tom));
28 }
29 }

执行规则

执行结果如下:

源码解析

https://www.cnblogs.com/lay2017/p/12591966.html

深入了解原理,可以查看github源码:

https://github.com/j-easy/easy-rules

https://gitcode.net/mirrors/j-easy/easy-rules

转:

https://segmentfault.com/a/1190000022939252

java轻量级规则引擎easy-rules使用介绍的更多相关文章

  1. Java规则引擎 Easy Rules

    1.  Easy Rules 概述 Easy Rules是一个Java规则引擎,灵感来自一篇名为<Should I use a Rules Engine?>的文章 规则引擎就是提供一种可选 ...

  2. QLExpress 规则引擎使用介绍

    一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用.让业务规则定义简便而不失灵活.让业务人员就可以定义业务规则.支持标准的JAVA语法,还可以支持自定义操作符号.操作符号重载. ...

  3. JAVA规则引擎 -- Drools

    Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  4. [Drools]JAVA规则引擎 -- Drools

    Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  5. [Drools]JAVA规则引擎 -- Drools- 转http://blog.csdn.net/quzishen/article/details/6163012

    [Drools]JAVA规则引擎 -- Drools 标签: java引擎exceptiongetterstringsetter 2011-01-25 14:33 113340人阅读 评论(35) 收 ...

  6. 使用规则引擎Drools计算圆周率PI

    实际上是使用规则引擎能够更新工作内存区重新匹配规则实现迭代功能. 使用了策略模式实现. <规则引擎与RETE算法介绍> PPT : http://files.cnblogs.com/lov ...

  7. 规则引擎QLExpress的简单应用

    QLExpress 是一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用.让业务规则定义简便而不失灵活.让业务人员就可以定义业务规则.支持标 准的JAVA语法,还可以支持自定义 ...

  8. SpringBoot2 整合 Drools规则引擎,实现高效的业务规则

    本文源码:GitHub·点这里 || GitEE·点这里 一.Drools引擎简介 1.基础简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的 ...

  9. (十五)整合 Drools规则引擎,实现高效的业务规则

    整合 Drools规则引擎,实现高效的业务规则 1.Drools引擎简介 1.1 规则语法 2.SpringBoot整合Drools 2.1 项目结构 2.2 核心依赖 2.3 配置文件 3.演示案例 ...

  10. JAVA规则引擎JSR-94笔札

    JAVA规则引擎JSR-94笔札 JSR-94 是由JCP(Java Community Process)组织所制定的java规则引擎API的java请求规范.它主要定义了规则引擎在java运行时的一 ...

随机推荐

  1. [转帖]Arm发布CortexX4,功耗可降低40%

    https://www.eet-china.com/mp/a224124.html ARM 发布了新一代的移动处理器内核,包括 Cortex-X4.Cortex-A720.Cortex-A520,预计 ...

  2. 【转帖】JVM 元数据区的内存泄漏之谜

    https://www.infoq.cn/article/Z111FLot92PD1ZP3sbrS 一.问题描述 某天,SRE 部门观察到一个非常重要的应用里面有一台服务器的业务处理时间(Transa ...

  3. [转帖]浅谈redis采用不同内存分配器tcmalloc和jemalloc

    http://www.kaotop.com/it/173669.html 我们知道Redis并没有自己实现内存池,没有在标准的系统内存分配器上再加上自己的东西.所以系统内存分配器的性能及碎片率会对Re ...

  4. Linux运行服务的几种方式

    摘要 1. nohup & 2. screen 3. bg & disown 4. systemd 5. crontab @reboot 背景 最近一直在用linux 想着多总结一下. ...

  5. 二进制安装Mysql数据库的快速方法

    二进制安装Mysql数据库的快速方法 摘要 还是国产操作系统 rpm包可能不太兼容,为了简单准备使用tar包方式安装mysql数据库 这里简单记录一下过程. 为以后使用. 介质下载 下载二进制的tar ...

  6. 使用Configmap 配置 springboot的application.yaml文件的方式部署环境的方法

    Configmap部署k8s下Springboot服务的办法 前提 日常工作中需要使用k8s部署微服务环境, 但是内部的数据库连接和redis等连接非常麻烦,使用helm chart 进行变量替换时非 ...

  7. apb vnext DynamicCient

    1.在需要的服务客户端(xx.HttpApi.Client)Nuget 引用和模块依赖 引用:VOLO.APB.HTTP.CLENT [dependsOn(typeof(AbpHttpClientMo ...

  8. Fabric网络升级(三)

    原文来自这里. 如果不熟悉capability,那么操作前可以查阅Capabilities.需要注意的是在启用capabilities前,需要升级归属该通道的peer节点和排序节点. 更多关于最新版F ...

  9. P9805 [POI2022~2023R1] ply

    1st思路 贪心 当遇到左括号深度加一,可如果当前深度大于 \(H\) 时深度减二,并且 \(ans\) 加一.相当于进行一次翻转操作. 当遇到右括号深度减一,当深度小于零时深度加二,并且 \(ans ...

  10. SqlSugar多库/多租户

    1. 多库和多租户 如果是接口ISugarClient先看一下标题6,看完在看这儿 1.1 固定多数据库模式 数据库数量是固定的一般在声明的全部加上 //通过ConfigId进行数据库区分 var d ...