规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。
规则引擎具体执行可以分为接受数据输入,解释业务规则,根据业务规则做出业务决策几个过程。
使用规则引擎可以把复杂、冗余的业务规则同整个支撑系统分离开,做到架构的可复用移植。
规则引擎的应用
相对于业务系统,规则引擎可以认为是一个独立于业务系统的模块,负责一些规则的计算等。
一般来说,规则引擎主要应用在下面的场景中:
- 风控模型配置,风控是规则引擎
- 用户积分等配置,如日常操作引起积分变化等
- 简单的离线计算,各类数据量比较小的统计等
常用规则引擎的选型
目前的规则引擎系统中,使用较多的开源规则引擎是Drools,另外还有商用的规则管理系统BRMS是ILOG JRules。
Drools
Drools是一个基于Java的开源规则引擎,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。
目前版本是5.0.1,Drools从5.0后分为四个模块:
- Drools Guvnor (BRMS/BPMS)
- Drools Expert (rule engine)
- Drools Flow (process/workflow)
- Drools Fusion (cep/temporal reasoning)
[drools应用文档](https://github.com/kiegroup/droolsjbpm-build-bootstrap/blob/master/README.md
)
Ilog JRules
Ilog Jrules是完整的业务规则管理系统(BRMS),它提供了对整个企业业务规则进行建模、编写、测试、部署和维护所必需的所有工具。
Ilog Jrules主要包括以下4个组件:
- Rule Studio(RS) 面向开发人员使用的开发环境,用于规则的建模和编写
- Rule Scenario Manager 规则测试工具
- Rule Team Server(RTS) 基于Web的管理环境,面向业务人员使用,用于规则发布、管理、存储
- Rule Execution Server(RES) 面向运维人员使用,用于规则执行、监控
[Ilog Jrules主页](https://www-01.ibm.com/software/integration/business-rule-management/jrules-family/
)
这两款规则引擎设计和实现都比较复杂,学习成本高,适用于大型应用系统。
Easy Rules
Easy Rules是我偶然间看到的一个规则引擎实现,相比Drools等企业级规则引擎,Easy Rules的应用非常简单,学习成本低,容易上手。
下面重点介绍这款轻量级的规则引擎 Easy Rules。
轻量级规则引擎Easy Rules
Easy Rules官方主页:http://www.easyrules.org/
Easy Rules提供以下功能:
- 轻量级框架和易于学习的API
- 基于POJO的开发
- 通过高效的抽象来定义业务规则并轻松应用它们
- 支持创建复合规则
Easy Rules的应用
Easy rules的工程可以从Github下载,构建需要Maven支持。
$ git clone https://github.com/EasyRules/easyrules.git
$ cd easyrules
$ mvn install
Easy Rules打包后是一个单独的jar,使用时需要添加相关文件到工程中,或者添加Maven依赖:
<dependency>
<groupId>org.easyrules</groupId>
<artifactId>easyrules-core</artifactId>
<version>2.4.0</version>
</dependency>
配置你的业务规则
大多数业务规则可以表示为以下定义:
- 名称:一种唯一的规则名称
- 描述:对规则的简要描述
- 优先级:相对于其他规则的优先级
- 条件:设置规则执行时需要满足的条件
- 操作:设置的条件满足时执行的操作
我们可以通过扩展Easy Rules提供的Rule interface来定义规则,或者通过注解,定义自己的规则类。
下面是内置的Rule接口:
package org.easyrules.api;
public interface Rule {
<span class="hljs-comment">/**
* 这个方法定义了规则执行的条件
* <span class="hljs-doctag">@return</span> true if the rule should be applied, false else
*/</span>
<span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">evaluate</span><span class="hljs-params">()</span></span>;
<span class="hljs-comment">/**
* 这个方法定义了规则执行的具体动作
* <span class="hljs-doctag">@throws</span> Exception if an error occurs
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception</span>;
<span class="hljs-comment">//Getters and setters for rule name,</span>
<span class="hljs-comment">//description and priority omitted.</span>
}
创建规则引擎
Easy Rules的引擎实例会维护一个不同规则的注册空间,每个Engine可以被视为一个单独的名称空间。
多条规则将会按照他们的自然顺序去执行,也就是默认的优先级。
要创建一个规则引擎和注册规则,可以使用下面的静态方法:
RulesEngineBuilder.aNewEngineBuilder():
RulesEngine rulesEngine = aNewEngineBuilder().build();
rulesEngine.registerRule(myRule);
执行下面的操作启动规则执行:
rulesEngine.fireRules();
Easy Rules应用实例
下面通过一个简单的Hello World示例来展示Easy Rules的具体应用。
通过注解创建一个具体的规则类:
@Rule(name = "Hello World rule",
description = "Say Hello to duke's friends only")
public class HelloWorldRule {
<span class="hljs-comment">/**
* The user input which represents the data
* that the rule will operate on.
*/</span>
<span class="hljs-keyword">private</span> String input;
<span class="hljs-meta">@Condition</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">checkInput</span><span class="hljs-params">()</span> </span>{
<span class="hljs-comment">//The rule should be applied only if</span>
<span class="hljs-comment">//the user's response is yes (duke friend)</span>
<span class="hljs-keyword">return</span> input.equalsIgnoreCase(<span class="hljs-string">"yes"</span>);
}
<span class="hljs-meta">@Action</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sayHelloToDukeFriend</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
<span class="hljs-comment">//When rule conditions are satisfied,</span>
<span class="hljs-comment">//prints 'Hello duke's friend!' to the console</span>
System.out.println(<span class="hljs-string">"Hello duke's friend!"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setInput</span><span class="hljs-params">(String input)</span> </span>{
<span class="hljs-keyword">this</span>.input = input;
}
}
接下来创建一个规则引擎的实例,注册并且启动这个规则:
public class Launcher {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(<span class="hljs-params">String[] args</span>) </span>{
Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.<span class="hljs-keyword">in</span>);
System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Are you a friend of duke?[yes/no]:"</span>);
String input = scanner.nextLine();
<span class="hljs-comment">/**
* Declare the rule
*/</span>
HelloWorldRule helloWorldRule = <span class="hljs-keyword">new</span> HelloWorldRule();
<span class="hljs-comment">/**
* Set business data to operate on
*/</span>
helloWorldRule.setInput(input.trim());
<span class="hljs-comment">/**
* Create a rules engine and register the business rule
*/</span>
RulesEngine rulesEngine = aNewRulesEngine().build();
rulesEngine.registerRule(helloWorldRule);
<span class="hljs-comment">/**
* Fire rules
*/</span>
rulesEngine.fireRules();
}
}
规则启动后会通过一个简单的条件判断(控制台输入),然后执行接下来的动作(输出规则信息)。
除了规则引擎基础的规则执行功能, Easy Rules还支持监听规则执行情况,为规则执行配置调度器,
集成Spring等功能。
关于规则引擎的选型和简单应用就介绍到这里,除了风控等大型的应用系统,一些独立的小型产品需求中,可以合理应用规则引擎实现业务与规则的分离,降低系统间耦合,上面介绍的Easy Rules就是一个不错的选择。
<!-- 登录查看 begin -->
<!-- 登录查看 end -->
</div>