我们在写业务代码经常遇到需要一大堆if/else,会导致代码可读性大大降低,有没有一种方法可以避免代码中出现大量的判断语句呢?答案是用规则引擎,但是传统的规则引擎都比较重,比如开源的Drools,不适合在小需求中应用。最近在github上面看到一个傻瓜式的Java规则引擎Easy-Rules,这里结合自己写的demo介绍如何使用这个规则引擎,希望对大家有所帮助。

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

它主要包括几个主要的类或接口:Rule,RulesEngine,RuleListener,Facts 
还有几个主要的注解:@Action,@Condition,@Fact,@Priority,@Rule

例1:基于POJO开发与注解的编程模型:判断1-50中,被3或者8整除的数
  • 首先maven 引入easy-rules
      <dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-mvel</artifactId>
<version>3.3.0</version>
</dependency>
  • 编写规则POJO:
@Rule(name = "被3整除", description = "number如果被3整除,打印:number is three")
public class ThreeRule {
@Condition //条件判断注解:如果return true, 执行Action
public boolean isThree(@Fact("number") int number){
return number % 3 == 0;
} @Action //执行方法注解
public void threeAction(@Fact("number") int number){
System.out.print(number + " is three");
} @Priority //优先级注解:return 数值越小,优先级越高
public int getPriority(){
return 1;
}
}
@Rule(name = "被8整除")
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.print(number + " is eight");
} @Priority
public int getPriority(){
return 2;
}
}
@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;
}
}
@Rule(name = "既不被3整除也不被8整除", description = "打印number自己")
public class OtherRule {
@Condition
public boolean isOther(@Fact("number") int number){
return number % 3 != 0 || number % 8 != 0;
} @Action
public void printSelf(@Fact("number") int number){
System.out.print(number);
} @Priority
public int getPriority(){
return 3;
}
}
  • 执行规则
public class ThreeEightRuleLauncher {

    public static void main(String[] args) {
/**
* 创建规则执行引擎
* 注意: skipOnFirstAppliedRule意思是,只要匹配到第一条规则就跳过后面规则匹配
*/
RulesEngineParameters parameters = new
RulesEngineParameters().skipOnFirstAppliedRule(true);
RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
//创建规则
Rules rules = new Rules();
rules.register(new EightRule());
rules.register(new ThreeRule());
rules.register(new ThreeEightRuleUnitGroup(new EightRule(), new ThreeRule()));
rules.register(new OtherRule());
Facts facts = new Facts();
for (int i=1 ; i<=50 ; i++){
//规则因素,对应的name,要和规则里面的@Fact 一致
facts.put("number", i);
//执行规则
rulesEngine.fire(rules, facts);
System.out.println();
}
}
}
  • 我们可以得到执行结果
1
2
3 is three
4
5
6 is three
7
8 is eight
9 is three
10
11
12 is three
13
14
15 is three
16 is eight
17
18 is three
19
20
21 is three
22
23
24 is three24 is eight
25
26
27 is three
28
29
30 is three
31
32 is eight
33 is three
34
35
36 is three
37
38
39 is three
40 is eight
41
42 is three
43
44
45 is three
46
47
48 is three48 is eight
49
50
例2:基于MVEL表达式的编程模型

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

public class Person {
private String name; private boolean adult; private int age;
//getter, setter 省略
}

我们定义两个规则:

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

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

规则1的定义

 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);");

规则2的定义,我们放到alcohol-rule.yml文件中

name: "alcohol rule"
description: "children are not allowed to buy alcohol"
priority: 2
condition: "person.isAdult() == false"
actions:
- "System.out.println(\"Shop: Sorry, you are not allowed to buy alcohol\");"
  • 执行规则
public class ShopLauncher {
public static void main(String[] args) throws Exception {
//创建一个Person实例(Fact)
Person tom = new Person("Tom", 14);
Facts facts = new Facts();
facts.put("person", tom); //创建规则1
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);");
//创建规则2
Rule alcoholRule = MVELRuleFactory.createRuleFrom(new FileReader("alcohol-rule.yml")); Rules rules = new Rules();
rules.register(ageRule);
rules.register(alcoholRule); //创建规则执行引擎,并执行规则
RulesEngine rulesEngine = new DefaultRulesEngine();
System.out.println("Tom: Hi! can I have some Vodka please?");
rulesEngine.fire(rules, facts);
}
}
  • 执行结果如下:本篇主要介绍easy-rules的使用

easy-rules的更多相关文章

  1. Java规则引擎 Easy Rules

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

  2. 小明历险记:规则引擎drools教程一

    小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...

  3. Java中动态规则的实现方式

    背景 业务系统在应用过程中,有时候要处理“经常变化”的部分,这部分需求可能是“业务规则”,也可能是“不同的数据处理逻辑”,这部分动态规则的问题,往往需要可配置,并对性能和实时性有一定要求. Java不 ...

  4. 实时营销引擎在vivo营销自动化中的实践 | 引擎篇04

    作者:vivo 互联网服务器团队 本文是<vivo营销自动化技术解密>的第5篇文章,重点分析介绍在营销自动化业务中实时营销场景的背景价值.实时营销引擎架构以及项目开发过程中如何利用动态队列 ...

  5. The Nine Indispensable Rules for HW/SW Debugging 软硬件调试之9条军规

    I read this book in the weekend, and decided to put the book on my nightstand. It's a short and funn ...

  6. Website Speed Optimization Guide for Google PageSpeed Rules

    原链接地址:http://www.artzstudio.com/2016/07/website-speed-optimization-guide-for-google-pagespeed-rules/ ...

  7. jQuery Easy UI 开发笔记

    1.jQuery Easy UI主要的运行原理是通过核心的代码调用插件来实现UI效果的 2.jQuery Easy UI插件与插件之间的关系是: 一.独立式插件: 独立式插件是指:不与其他的插件具有相 ...

  8. acdream.A Very Easy Triangle Counting Game(数学推导)

    A - A Very Easy Triangle Counting Game Time Limit:1000MS     Memory Limit:64000KB     64bit IO Forma ...

  9. 转载:10 Easy Steps to a Complete Understanding of SQL

    10 Easy Steps to a Complete Understanding of SQL 原文地址:http://tech.pro/tutorial/1555/10-easy-steps-to ...

  10. [转]java-Three Rules for Effective Exception Handling

    主要讲java中处理异常的三个原则: 原文链接:https://today.java.net/pub/a/today/2003/12/04/exceptions.html Exceptions in ...

随机推荐

  1. 【巨杉数据库SequoiaDB】企业级和开源领域“两开花”,巨杉引领国产数据库创新

    2019年12月15日,OSC 源创会·年终盛典在深圳圆满举行.巨杉数据库作为业界领先的金融级分布式数据库厂商, 获得 “2019年开源数据库先锋企业” 及 “2019 GVP-Gitee最有价值开源 ...

  2. C# Timer 控件的用法

    一.主要的属性 在 Windows 窗体应用程序中,定时器控件(Timer)与其他的控件略有不同,它并不直接显示在窗体上,而是与其他控件连用. Enabled 属性: 用于设置该Timer控件是否可用 ...

  3. AUI前端框架总结

    AUI 是Apicloud 的手机端UI第三方,需要引入Apicloud和AUI中的css样式和js框架 **首先:手机项目必须配置config.xml文件 Apicloud官网有详解 ** 其次:程 ...

  4. 如何面试QA(面试官角度)

    面试是一对一 或者多对一的沟通,是和候选人 互相交换信息.平等的. 面试的目标是选择和雇佣最适合的人选.是为了完成组织目标.协助人力判断候选人是否合适空缺职位. 面试类型: (1)预判面试(查看简历后 ...

  5. CentOS7利用docker安装MySQL5.7

    CentOS7利用docker安装MySQL5.7 前提条件 centos7 且内核版本高于3.10, 可通过以下命令查看内核版本 uname -r 利用yum 安装docker 安装一些必要的系统工 ...

  6. 自定义jstl标签*

    原文链接:https://www.it610.com/article/442039.htm 步骤如下: 1.写tld文档:用来指定标签的名字,标签库等. 2.写标签处理器类. 3.配置到web.xml ...

  7. 第四篇,JavaScript面试题汇总

    JavaScript是一种属于网络的脚本语言,已经被广泛用于web实用开发,常用来为网页添加各种各样的动态功能,为用户提供更流畅美观的浏览效果.通常JavaScript脚本是通过嵌入在HTML中来实现 ...

  8. 从零开始教你做高保真原型图+UI 设计规范

    编者按:<从零开始设计App>系列到这篇已经是第三期了,上期是低保真原型图,这期@Sophia的玲珑阁 聊聊如何从零开始制作高保真原型图和UI 设计规范. 往期回顾: <设计师怎样从 ...

  9. MySQL条件查询

    语法: ①SELECT 查询列表(可以包括:字段.表达式.常量值.几个拼在一起的,构成的表) ②FROM 表名(原始表) ③WHERE (理解为当...筛选条件=TRUE或筛选条件=FALSE) 筛选 ...

  10. DE1-LINUX运行

    在官网下载.img文件:网址:http://download.terasic.com/downloads/cd-rom/de1-soc/linux_BSP/ 写入DE1_SOC_SD.img文件: 打 ...