什么是规则引擎(Drools、OpenL Tablets、Easy Rules、RuleBook)

什么是规则引擎

规则引擎是根据一些算法执行规则的一些列软件系统。规则引擎整合了传入系统的Fact集合和规则集合,从而去触发一个或多个业务操作。规则通常以声明式的方式在业务代码中实现,我们可能以为它很少会被改变。但事实上,这些业务逻辑的判断条件经常会被改变。

在本篇文章中的业务逻辑或规则,通常是可以表示为“在某写条件下,执行某些任务”。

在拥有大量规则和Fact对象的业务系统中,可能会出现多个Fact输入都会导致同样的输出,这种情况我们通常称作规则冲突。规则引擎可以采用不同的冲突解决方案来确定冲突规则的执行顺序。在规则引擎中,通常有两种执行方式:


正向链接:这是一种基于“数据驱动”的形式,基于插入的Fact对象和Fact对象的更新,规则引擎利用可用的Fact推理规则来提取出更多的Fact对象,直到计算出最终目标,最终会有一个或多个规则被匹配,并计划执行。因此,规则引擎始于事实,始于结论。


反向链接:这是一种基于“目标驱动”或推理形式,与正向链接相反。反向链条从规则引擎假设的结论开始,如果不能够直接满足这些假设,则搜索可满足假设的子目标。规则引擎会循环执行这一过程,直到证明结论或没有更多可证明的子目标为止。

规则引擎与流程处理的区别

规则与过程的不同之处主要在于:业务流程代表业务做了什么;规则引擎代表决定做什么业务。


规则引擎可以被视为复杂的if / then语句解释器。被解释的if / then语句称为规则。


规则的if部分用于处理条件,比如account.getMoney() < 0;规则的then部分包含执行的操作,比如sendWarning(account)。

if (account.getMoney() < 0)

sendWarning(account);

什么是规则引擎(Drools、OpenL Tablets、Easy Rules、RuleBook)插图

规则存储在正向链接规则引擎中,即引擎执行一个执行周期,该周期允许一个规则的操作触发其他规则的条件得到满足。这样,级联的规则会被激活,同时每条规则的操作都会被执行。正向链接的规则引擎适用于从简单输入(Fact)得出高层次的结论的场景。

上面的代码示例,通过规则引擎可写成如下形式:

global AccountManager manager;

rule "checkMoney"

when

$account : Account( money < 0 )

then

manager.warn($account);

end

显而易见,一个规则文件是由两个概念组成:
规则:用于控制业务流程的声明式语句。一个规则通常包含判断条件部分和执行操作部分。如果条件评估结果为true,则执行规则引擎操作部分。
Fact:规则执行所需要的数据。在上面的示例中Account便是Fact对象。

规则引擎的优势

使用规则引擎可以给系统带来如下优势:
高灵活性:在规则保存在知识库中,可以在规则变动轻易做出修改。
容易掌控:规则比过程代码更易于理解,因此可以有效地来弥补业务分析师和开发人员之间的沟通问题。
降低复杂度:在程序中编写大量的判断条件,很可能是会造成一场噩梦。使用规则引擎却能够通过一致的表示形式,更好的处理日益复杂的业务逻辑。
可重用性:规则集中管理,可提高业务的规则的可重用性。而且,传统的代码程序通常会添加不必要的变数,很然进行重复利用。


需要留意的是,在业务规则没有太多变动,业务规则比较简单的情况下,是没有必要使用规则引擎的。

开源规则引擎

Drools规则引擎是一款开源的规则引擎,地址为:Drools - Business Rules Management System (Java™, Open Source) 。Drools规则引擎可通过存储、处理和评估数据来执行业务规则和决策模型。Drools规则引擎最基础的功能是将输入的数据或Fact对象和规则条件进行匹配,并根据匹配结果决定如何执行规则。


Drools规则引擎基于以下组件运行:
规则:业务规则或DMN决策。所有规则必须至少包含触发该规则的条件以及对应的操作。

Fact:输入到规则引擎的数据,用于规则的条件的匹配。

生产内存:规则引擎中规则存储的地方。

工作内存:规则引擎中Fact对象存储的地方。

议程:用于存储被激活的规则的分类和排序的地方。

当用户或系统在Drools中添加或更新规则相关的信息时,该信息会以一个或多个Fact的形式插入Drools规则引擎的工作内存中。Drools规则引擎匹配Fact和存储在生产内存中规则,筛选符合执行条件的规则。对于满足条件的规则,规则引擎会在议程中激活和注册对应的规则,在议程中Drools会进行优先级的排序和冲突的解决,准备规则的执行。

下图概述了相关操作:

什么是规则引擎(Drools、OpenL Tablets、Easy Rules、RuleBook)插图1

Drools引擎是KIE(知识就是一切)项目的一部分,该项目除了Drools之外还包括:

jBPM:jBPM是一种灵活的业务流程管理组件,允许你通过描述实现这些目标所需执行的步骤来对业务目标进行建模。

OptaPlanner是一个约束解决器,可以优化用例,例如员工排班,车辆路线,任务分配和云优化。

Business Central是功能齐全的Web应用程序,用于可视化组成自定义业务规则和流程。

UberFire是一个基于Web的工作台框架,其灵感来自Eclipse Rich Client Platform。

Drool规则的示例,留意一下的Java Bean模型和示例DRL规则:

public class Applicant {

private String name;

private int age;

private boolean valid;

// Getter and setter methods

}

下面是一个用于检查申请人年龄的简单DRL规则示例:

package com.company.license

rule "Is of valid age"

when

$a : Applicant(age < 18)

then

$a.setValid(false);

end

上述规则,对于未满18岁的申请人,将会拒绝。

//Create the KIE container

KieServices kieServices = KieServices.Factory.get();

KieContainer kContainer = kieServices.getKieClasspathContainer();

//Instantiate the stateless KIE session and enter data

StatelessKieSession kSession = kContainer.newStatelessKieSession();

Applicant applicant = new Applicant("Mr John Smith", 16);

assertTrue(applicant.isValid());

ksession.execute(applicant);

assertFalse(applicant.isValid());

OpenL Tablets

OpenL Tablets(http://openl-tablets.org/)是基于Excel文档的业务规则管理系统和业务规则引擎。基于独特的概念,OpenL Tablets有助于将包含业务逻辑规范的业务文档视为可执行源代码。由于企业用户熟悉OpenL Tablets使用的表格式,因此OpenL Tablets弥补了企业用户和开发人员之间的鸿沟,从而减少了昂贵的企业软件开发错误,并大大缩短了软件开发周期。 简单来说,可以将OpenL Tablets视为表处理器,该处理器可从Excel文档中提取表并可以通过应用程序访问。

OpenL Tablets主要优点:

  • OpenL Tablets消除了软件实施与业务文档,规则和策略之间的鸿沟。
  • 业务规则对开发人员变得透明。
  • OpenL Tablets验证所有项目文档数据中的语法和类型错误,从而提供方便且详细的错误报告。 OpenL Tablets可以直接指向Excel文档中的问题。
  • OpenL Tablets提供了计算解释功能,可以通过指向原始文档中的源参数来扩展任何计算结果。
  • OpenL Tablets使用户能够创建和维护测试,以确保所有规则的可靠工作。
  • OpenL Tablets在所有项目文档中提供交叉索引和搜索功能。
  • OpenL Tablets通过其业务规则管理应用程序提供完整的规则生命周期支持。
  • OpenL Tablets支持.xls和.xlsx文件格式。

使用OpenL Tablets API可访问Excel表中的规则和数据。 OpenL Tablets提供了一个包装器,以方便使用。 例如,考虑以下在Excel文档中编码的规则:

什么是规则引擎(Drools、OpenL Tablets、Easy Rules、RuleBook)插图2

在hello1中只有一个规则:

public interface Simple {

void hello1(int i);

}

基于包装器运行规则:

import static java.lang.System.out;

import org.openl.rules.runtime.RulesEngineFactory;

public class Example {

public static void main(String[] args) {

//define the interface

RulesEngineFactory < Simple > rulesFactory =

new RulesEngineFactory < Simple > ("TemplateRules.xls",

Simple.class);

Simple rules = (Simple) rulesFactory.newInstance();

rules.hello1(12);

}

}

使用OpenL Tablets,需要引入如下依赖:

<dependency>

<groupId>com.deliveredtechnologies</groupId>

<artifactId>rulebook-core</artifactId>

<version>0.11</version>

</dependency>

Easy Rules

Easy Rules(https://github.com/j-easy/easy-rules)是一个简单但功能强大的Java规则引擎,提供以下功能:

  • 轻巧的框架和易于学习的API
  • 基于POJO的开发
  • 抽象定义业务规则,可轻松使用
  • 支持从原始规则创建复合规则
  • 支持使用表达式语言(如MVEL和SpEL)定义规则

简而言之,Easy Rules提供了Rule抽象以创建具有条件和操作的规则,并提供了RuleEngine API,该API通过一组规则去评估条件并执行操作。
要使Easy Rules需引入以下依赖项到pom.xml中:

<dependency>

<groupId>org.jeasy</groupId>

<artifactId>easy-rules-core</artifactId>

<version>3.4.0</version>

</dependency>

创建一个始终会触发,并打印“hello word”到控制台的规则:

@Rule(name = "Hello World rule", description = "Always say hello world")

public class HelloWorldRule {

@Condition

public boolean when() {

return true;

}

@Action

public void then() throws Exception {

System.out.println("hello world");

}

}

创建规则引擎,并触发规则:

public class Launcher {

public static void main(String[] args) {

// create facts

Facts facts = new Facts();

// create rules

Rules rules = new Rules();

rules.register(new HelloWorldRule());

// create a rules engine and fire rules on known facts

RulesEngine rulesEngine = new DefaultRulesEngine();

rulesEngine.fire(rules, facts);

}

}

RuleBook规则引擎

厌倦了充斥着if/then/else语句类?是否需要一个很好的抽象方法,以使规则彼此分离的方式轻松指定规则?是否要像编写其余代码一样编写规则?RuleBook可能是你要选择的规则抽象。

RuleBook是一个规则引擎,旨在以Java开发人员熟悉的方式创建规则。RuleBook还允许你使用易于使用的启用Lambda的特定领域语言或自定义的POJO来指定规则。

使用RuleBook需要引入以下依赖到pom.xml中:

<dependency>

<groupId>com.deliveredtechnologies</groupId>

<artifactId>rulebook-core</artifactId>

<version>0.11</version>

</dependency>

使用示例:

public class ExampleRule {

public RuleBook<Object> defineHelloWorldRules() {

return RuleBookBuilder

.create()

.addRule(rule -> rule.withNoSpecifiedFactType()

.then(f -> System.out.print("Hello ")))

.addRule(rule -> rule.withNoSpecifiedFactType()

.then(f -> System.out.println("World")))

.build();

}

}

通过以下方式执行:

public static void main(String[] args) {

ExampleRule ruleBook = new ExampleRule();

ruleBook

.defineHelloWorldRules()

.run(new FactMap<>());

}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐