规则引擎,全称:业务规则管理系统,英文名为BRMS(Business Rule Management System)。

规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。

可降低组件业务逻辑复杂性、降低应用程序的维护和可扩展性成本的组件

适用场景

业务规则经常变化,系统需依据业务的变化,实现快速、低成本的迭代更新。

规则系统特别适合以下场景:

  1. 业务规则频繁变化 - 营销策略、风控规则等

  2. 复杂决策逻辑 - 需要多条件组合判断的场景

  3. 需要业务人员参与 - 非技术人员需要配置规则

  4. 高可配置性要求 - 不同客户需要不同的规则集

  5. 审计和合规要求 - 需要记录和追踪规则变更

因此,为了快速、低成本的更新,我们需将逻辑代码和业务代码进行解耦:

  • 业务规则与系统代码分离,实现业务规则的集中管理

  • 业务人员可直接管理这些业务规则,同时不需要研发人员的参与。

  • 稳定层和变化层分离,是一种优秀的设计模式;

  • 变化层支持可视化或配置化方式,快速进行业务规则的增删改操作,甚至支持热插拔和热更新。以减少冗长的开发和测试周期;

  • 部分规则引擎甚至带有设计器(如drools),还可解决我们 “简式建模” 的需求。

对于一些存在比较复杂的业务规则并且业务规则会频繁变动的系统比较适合使用规则引擎,如下:

1、风险控制系统----风险贷款、风险评估

2、反欺诈项目----银行贷款、征信验证

3、决策平台系统----财务计算

4、促销平台系统----满减、打折、加价购

风控与反欺诈系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 金融风控规则
@Rule(name = "高风险交易检测", priority = 1)
public class HighRiskTransactionRule {

@Condition
public boolean isHighRisk(@Fact("transaction") Transaction transaction) {
return transaction.getAmount() > 10000 ||
transaction.isInternational();
}

@Action
public void flagForReview(@Fact("transaction") Transaction transaction) {
transaction.setRiskLevel(RiskLevel.HIGH);
System.out.println("交易金额过大或跨境,需要人工审核");
}
}

@Rule(name = "可疑行为检测", priority = 2)
public class SuspiciousBehaviorRule {

@Condition
public boolean isSuspicious(@Fact("user") User user,
@Fact("transaction") Transaction transaction) {
return user.getLoginLocation().equals("异地") &&
transaction.getAmount() > 5000;
}

@Action
public void triggerAlert() {
alertService.sendAlert("检测到可疑交易行为");
}
}

营销与促销系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 电商促销规则
@Rule(name = "新用户优惠", priority = 1)
public class NewUserDiscountRule {

@Condition
public boolean isNewUser(@Fact("user") User user,
@Fact("order") Order order) {
return user.isNewUser() && order.getAmount() > 100;
}

@Action
public void applyDiscount(@Fact("order") Order order) {
order.applyDiscount(0.1); // 新用户9折
System.out.println("新用户享受9折优惠");
}
}

@Rule(name = "会员日促销", priority = 2)
public class MemberDayRule {

@Condition
public boolean isMemberDay(@Fact("date") LocalDate date,
@Fact("user") User user) {
return date.getDayOfMonth() == 8 && // 每月8号会员日
user.isVIP();
}

@Action
public void applyMemberDiscount(@Fact("order") Order order) {
order.applyDiscount(0.15); // 会员日85折
System.out.println("会员日享受85折优惠");
}
}

审批工作流系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 贷款审批规则集
public class LoanApprovalWorkflow {

@Rule(name = "基础资格检查", priority = 1)
public class BasicEligibilityRule {
@Condition
public boolean checkBasic(@Fact("application") LoanApplication app) {
return app.getAge() >= 22 && app.getAge() <= 60;
}

@Action
public void markEligible(@Fact("result") ApprovalResult result) {
result.addQualification("年龄符合要求");
}
}

@Rule(name = "收入要求检查", priority = 2)
public class IncomeRequirementRule {
@Condition
public boolean checkIncome(@Fact("application") LoanApplication app) {
return app.getMonthlyIncome() >= app.getLoanAmount() * 0.3;
}

@Action
public void markIncomeQualified(@Fact("result") ApprovalResult result) {
result.addQualification("收入符合要求");
}
}
}

智能路由与推荐系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 客服工单路由规则
@Rule(name = "技术问题路由", priority = 1)
public class TechnicalIssueRouteRule {

@Condition
public boolean isTechnicalIssue(@Fact("ticket") SupportTicket ticket) {
return ticket.getCategory().equals("技术问题") ||
ticket.getKeywords().contains("bug");
}

@Action
public void routeToTechTeam(@Fact("ticket") SupportTicket ticket) {
ticket.assignTo("技术支持团队");
System.out.println("技术问题已路由到技术支持团队");
}
}

@Rule(name = "VIP客户优先路由", priority = 2)
public class VIPCustomerRouteRule {

@Condition
public boolean isVIPCustomer(@Fact("user") User user,
@Fact("ticket") SupportTicket ticket) {
return user.isVIP() && ticket.getPriority() == Priority.HIGH;
}

@Action
public void routeToSeniorStaff(@Fact("ticket") SupportTicket ticket) {
ticket.assignTo("高级客服专员");
System.out.println("VIP客户问题已路由到高级专员");
}
}

数据验证与清洗系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 数据质量检查规则
@Rule(name = "数据完整性检查", priority = 1)
public class DataCompletenessRule {

@Condition
public boolean hasMissingFields(@Fact("data") DataRecord record) {
return record.getField("name") == null ||
record.getField("email") == null;
}

@Action
public void flagIncomplete(@Fact("data") DataRecord record) {
record.setStatus(DataStatus.INCOMPLETE);
System.out.println("数据记录缺少必填字段");
}
}

@Rule(name = "数据格式验证", priority = 2)
public class DataFormatRule {

@Condition
public boolean hasFormatIssues(@Fact("data") DataRecord record) {
String email = record.getField("email");
return email != null && !isValidEmail(email);
}

@Action
public void flagFormatError(@Fact("data") DataRecord record) {
record.setStatus(DataStatus.FORMAT_ERROR);
System.out.println("邮箱格式不正确");
}
}

物联网设备监控系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 设备状态监控规则
@Rule(name = "温度异常告警", priority = 1)
public class TemperatureAlertRule {

@Condition
public boolean isTemperatureHigh(@Fact("sensor") SensorData sensor) {
return sensor.getTemperature() > 80; // 温度超过80度
}

@Action
public void triggerTemperatureAlert(@Fact("sensor") SensorData sensor) {
alertService.sendAlert("设备温度异常: " + sensor.getTemperature());
coolingSystem.activate(); // 启动冷却系统
}
}

@Rule(name = "设备离线检测", priority = 2)
public class DeviceOfflineRule {

@Condition
public boolean isDeviceOffline(@Fact("device") Device device) {
return System.currentTimeMillis() - device.getLastHeartbeat() > 300000; // 5分钟无心跳
}

@Action
public void triggerOfflineAlert(@Fact("device") Device device) {
alertService.sendAlert("设备离线: " + device.getId());
maintenanceTeam.notify(device);
}
}

医疗诊断辅助系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 医疗诊断规则
@Rule(name = "高血压风险评估", priority = 1)
public class HypertensionRiskRule {

@Condition
public boolean isHighRisk(@Fact("patient") Patient patient,
@Fact("exam") MedicalExam exam) {
return exam.getBloodPressure() > 140 &&
patient.getAge() > 50 &&
patient.hasFamilyHistory("高血压");
}

@Action
public void recommendCheckup(@Fact("patient") Patient patient) {
recommendationService.addRecommendation(
patient, "建议进行24小时动态血压监测");
}
}

不适用场景

  1. 规则极其简单且稳定 - 简单的if-else足以应对

  2. 性能要求极高 - 规则引擎有一定性能开销

  3. 规则间高度耦合 - 难以拆分为独立规则的情况

  4. 实时性要求极高 - 纳秒级响应的场景

LiteFlow(推荐)

将瀑布流式的代码,转变成以组件为核心概念的代码结构,这种结构的好处是可以任意编排,组件与组件之间是解耦的,组件可以用脚本来定义,组件之间的流转全靠规则来驱动。

LiteFlow只做基于逻辑的流转,而不做基于角色任务的流转(工作流引擎)

LiteFlow适用于拥有复杂逻辑的业务,比如说价格引擎,下单流程等,这些业务往往都拥有很多步骤,这些步骤完全可以按照业务粒度拆分成一个个独立的组件,进行装配复用变更。使用LiteFlow,你会得到一个灵活度高,扩展性很强的系统。因为组件之间相互独立,也可以避免改一处而动全身的这样的风险。

特性

  • 组件定义统一: 所有的逻辑都是组件,为所有的逻辑提供统一化的组件实现方式,小身材,大能量。

  • 规则轻量: 基于规则文件来编排流程,学习规则入门只需要5分钟,一看即懂。

  • 规则多样化: 规则支持xml、json、yml三种规则文件写法方式,喜欢哪种用哪个。

  • 任意编排: 再复杂的逻辑过程,利用LiteFlow的规则,都是很容易做到的,看规则文件就能知道逻辑是如何运转的。

  • 规则持久化: 框架原生支持把规则存储在标准结构化数据库,Nacos,Etcd,Zookeeper,Apollo,Redis。您也可以自己扩展,把规则存储在任何地方。

  • 优雅热刷新机制: 规则变化,无需重启您的应用,即时改变应用的规则。高并发下不会因为刷新规则导致正在执行的规则有任何错乱。

  • 支持广泛: 不管你的项目是不是基于Springboot,Spring还是任何其他java框架构建,LiteFlow都能游刃有余。

  • Springboot支持全面: 支持Springboot 2.X到最新的Springboot 3.X。

  • 脚本语言支持: 可以定义脚本语言节点,支持Groovy,Java,Kotlin,Javascript,QLExpress,Python,Lua,Aviator。未来还会支持更多的脚本语言。

  • 脚本和Java全打通: 所有脚本语言均可调用Java方法,甚至于可以引用任意的实例,在脚本中调用RPC也是支持的。

  • 规则嵌套支持: 只要你想的出,你可以利用简单的表达式完成多重嵌套的复杂逻辑编排。

  • 组件重试支持: 组件可以支持重试,每个组件均可自定义重试配置和指定异常。

  • 上下文隔离机制: 可靠的上下文隔离机制,你无需担心高并发情况下的数据串流。

  • 声明式组件支持: 你可以让你的任意类秒变组件。

  • 详细的步骤信息: 你的链路如何执行的,每个组件耗时多少,报了什么错,一目了然。

  • 稳定可靠: 历时2年多的迭代,在各大公司的核心系统上稳定运行。

  • 性能卓越: 框架本身几乎不消耗额外性能,性能取决你的组件执行效率。

  • 自带简单监控: 框架内自带一个命令行的监控,能够知道每个组件的运行耗时排行。

规则

支持很多规则,可参考 官网

  • 串行

    • THEN(a, b, c, d);
    • SER(a, b, c, d);
    • THEN(a, b, THEN(c, d));
  • 并行

    • WHEN(a, b, c);
    • PAR(a, b, c);
  • 选择

    • SWITCH(a).to(b, c, d); #组件a,来选择执行b,c,d中的一个
    • SWITCH(x).TO(a, b, c).DEFAULT(y); #添加默认执行
  • 条件

    • THEN(IF(x, a),b); #x为条件节点,为真的情况下,执行链路就为x->a->b,为假链路就为x->b
    • THEN(IF(x, a,b),c); # 三元表达式:x为条件节点,为真的情况下,执行链路就为x->a->c,为假链路就为x->b->c
    • IF(x, a).ELSE(b); 等于 IF(x, a, b); # 如果a为真 x->a,否则 x->b
  • 循环

    • FOR(5).DO(THEN(a, b)); 表示把a->b这个链路固定循环了5次
    • WHILE(w).DO(THEN(a, b));
    • ITERATOR(x).DO(THEN(a, b));
    • FOR(f).DO(THEN(a, b)).BREAK©; c这个节点需要为布尔组件,返回一个布尔值,为true则退出循环

使用

引入依赖和配置

1
2
3
4
5
6
7
8
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>2.12.4.1</version>
</dependency>

# application.yml 中引入配置
liteflow.rule-source=config/flow.el.xml

编排规则:config/flow.el.xml

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="chain1">
THEN(a, b, c);
</chain>
</flow>

实现规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 组件
@Component("a")
public class ACmp extends NodeComponent {

@Override
public void process() {
//do your business
}
}
@Component("b")
public class BCmp extends NodeComponent {

@Override
public void process() {
//do your business
}
}
@Component("c")
public class CCmp extends NodeComponent {

@Override
public void process() {
//do your business
}
}

调用规则

1
2
3
4
5
6
7
8
9
10
11
// 调用
@Component
public class YourClass{

@Resource
private FlowExecutor flowExecutor;

public void testConfig(){
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
}
}

Drools

由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。

Drools 是用Java语言编写的开放源码规则引擎,基于Apache协议,RETE算法。

Drools是一个绝对重量级的规则引擎,很多像金融行业、电信行业的大公司都在使用它作为规则引擎。

特性

  • 最活跃的开源规则引擎, 非常活跃的社区支持

  • 易用

  • 快速的执行速度

  • 基于java的规则引擎, 与 Java Rule Engine API(JSR 94)兼容

  • 易于访问企业策略、易于调整以及易于管理

  • 符合业内标准,速度快、效率高

  • 简化系统架构,优化应用。

  • 提高系统的可维护性和维护成本。

  • 方便系统的整合。

  • 减少编写“硬代码”业务规则的成本和风险。

  • 业务分析师无法独立完成规则配置:由于规则主体DSL是编程语言(Java, Groovy, Python),仍然需要开发工程师维护

  • 规则规模变大以后也会变得不好维护,相对硬编码的优势便不复存在

  • 规则的语法仅适合扁平的规则,对于嵌套条件语义(then里嵌套when…then子句)的规则只能将条件进行笛卡尔积组合以后进行配置,不利于维护。

原理

drools规则引擎由以下三部分构成:

  • Working Memory(工作内存):从中获取数据并和规则文件中定义的规则进行模式匹配

  • Rule Base(规则库):定义的规则都会被加载到规则库

  • Inference Engine(推理引擎

    • Pattern Matcher(匹配器):将Rule Base中的所有规则与Working Memory中的Fact对象(普通的JavaBean)进行模式匹配,匹配成功的规则将被激活并放入Agenda中。
    • Agenda(议程):存放通过匹配器进行模式匹配后被激活的规则
    • Execution Engine(执行引擎):执行Agenda中被激活的规则img

执行过程如下:

img

API 继承关系:

img

规则体语法结构规则体是规则文件内容中的重要组成部分,是进行业务规则判断、处理业务结果的部分。

1
2
3
4
5
6
7
rule "ruleName"
attributes
when
LHS
then
RHS
end

rule:关键字,表示规则开始,参数为规则的唯一名称。

attributes:规则属性,是rule与when之间的参数,为可选项。

when:关键字,后面跟规则的条件部分。

LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。

then:关键字,后面跟规则的结果部分。

RHS(Right Hand Side):是规则的后果或行动部分的通用名称。

end:关键字,表示一个规则结束。

使用

业务场景:消费者在图书商城购买图书,下单后需要在支付页面显示订单优惠后的价格。具体优惠规则如下:

规则编号 规则名称 描述
1 规则一 所购图书总价在100元以下的没有优惠
2 规则二 所购图书总价在100到200元的优惠20元
3 规则三 所购图书总价在200到300元的优惠50元
4 规则四 所购图书总价在300元以上的优惠100元

引入jar和配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.10.0.Final</version>
</dependency>

<!--根据drools要求创建resources/META-INF/kmodule.xml 规则配置文件-->
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是需要唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession名称,可以任意,但是需要唯一
default:指定当前session是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>

创建规则文件resources/rules/bookDiscount.drl(新建 Order 类,添加属性 originalPrice和realPrice)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//图书优惠规则
package book.discount
import com.demo.framework.brms.entity.Order
//规则一:所购图书总价在100元以下的没有优惠
rule "book_discount_1"
when
$order:Order(originalPrice < 100)
then
$order.setRealPrice($order.getOriginalPrice());
System.out.println("成功匹配到规则一:所购图书总价在100元以下的没有优惠");
end


//规则二:所购图书总价在100到200元的优惠20元
rule "book_discount_2"
when
$order:Order(originalPrice < 200 && originalPrice >= 100)
then
$order.setRealPrice($order.getOriginalPrice() - 20);
System.out.println("成功匹配到规则二:所购图书总价在100到200元的优惠20元");
end


//规则三:所购图书总价在200到300元的优惠50元
rule "book_discount_3"
when
$order:Order(originalPrice <= 300 && originalPrice >= 200)
then
$order.setRealPrice($order.getOriginalPrice() - 50);
System.out.println("成功匹配到规则三:所购图书总价在200到300元的优惠50元");
end


//规则四:所购图书总价在300元以上的优惠100元
rule "book_discount_4"
when
$order:Order(originalPrice >= 300)
then
$order.setRealPrice($order.getOriginalPrice() - 100);
System.out.println("成功匹配到规则四:所购图书总价在300元以上的优惠100元");
end

//指定规则:所购图书都优惠100元
rule "book_discount_order"
when
$order:Order(originalPrice >= 0)
then
$order.setRealPrice($order.getOriginalPrice() - 100);
System.out.println("指定规则:所购图书都优惠100元");
end

使用规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.demo.framework.brms.entity;
@Data
public class Order {
private Double originalPrice;//订单原始价格,即优惠前价格
private Double realPrice;//订单真实价格,即优惠后价格
}

@Test
public void test1() {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
//会话对象,用于和规则引擎交互
KieSession kieSession = kieClasspathContainer.newKieSession();
//构造订单对象,设置原始价格,由规则引擎根据优惠规则计算优惠后的价格
Order order = new Order();
order.setOriginalPrice(210D);
//将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配
kieSession.insert(order);
//激活规则引擎,如果规则匹配成功则执行规则
kieSession.fireAllRules();
//通过规则过滤器实现只执行指定规则
// kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("book_discount_order"));
//关闭会话
kieSession.dispose();
System.out.println("优惠前原始价格:" + order.getOriginalPrice() +
",优惠后价格:" + order.getRealPrice());
}

// 打印结果(匹配到规则三)
// 优惠前原始价格:210.0,优惠后价格:160.0

EsayRule

一个轻量级的 Java 规则引擎,它提供了简单而强大的方式来定义和执行业务规则。它的设计理念是让规则管理变得简单直观。

特性

  1. 轻量级 - 不依赖其他框架,核心包很小

  2. 简单易用 - 基于注解的规则定义

  3. 灵活 - 支持多种规则定义方式

  4. 可组合 - 规则可以组合成规则集

  5. 易于测试 - 规则可以独立测试

原理

EasyRule 的实现原理可以分为几个关键部分:规则定义、规则引擎、事实管理和执行流程。

  1. 策略模式 - 不同的规则执行策略

  2. 观察者模式 - 监听器机制

  3. 组合模式 - 组合规则

  4. 模板方法模式 - 规则执行流程

  5. 工厂模式 - 规则创建

  • 注解规则解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// EasyRule 内部通过反射解析注解规则
public class AnnotationRuleProxy implements Rule {

private final Object rule; // 规则对象实例
private final List<ConditionMethod> conditions;
private final List<ActionMethod> actions;

@Override
public boolean evaluate(Facts facts) {
// 通过反射调用 @Condition 方法
for (ConditionMethod condition : conditions) {
Object[] args = extractArguments(condition, facts);
Boolean result = (Boolean) condition.getMethod().invoke(rule, args);
if (!result) return false;
}
return true;
}

@Override
public void execute(Facts facts) {
// 通过反射调用 @Action 方法
for (ActionMethod action : actions) {
Object[] args = extractArguments(action, facts);
action.getMethod().invoke(rule, args);
}
}
}
  • 优先级调度原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 规则优先级比较器
public class RulePriorityComparator implements Comparator<Rule> {

@Override
public int compare(Rule rule1, Rule rule2) {
// 优先级数字越小,优先级越高
return Integer.compare(rule1.getPriority(), rule2.getPriority());
}
}

// 在规则引擎中的使用
public List<Rule> sort(Rules rules) {
List<Rule> ruleList = new ArrayList<>();
for (Rule rule : rules) {
ruleList.add(rule);
}
Collections.sort(ruleList, new RulePriorityComparator());
return ruleList;
}
  • DefaultRulesEngine 核心逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class DefaultRulesEngine implements RulesEngine {

private final RulesEngineParameters parameters;

@Override
public void fire(Rules rules, Facts facts) {
// 1. 规则排序(按优先级)
List<Rule> ruleList = sort(rules);

// 2. 应用规则引擎参数
ruleList = applyRulePriorityThreshold(ruleList);

// 3. 规则触发检查
for (Rule rule : ruleList) {
if (parameters.isSkipOnFirstAppliedRule() && triggered) {
break; // 跳过后续规则
}

// 4. 评估规则条件
if (rule.evaluate(facts)) {
// 5. 执行规则动作
rule.execute(facts);
triggered = true;

if (parameters.isSkipOnFirstAppliedRule()) {
break;
}
}
}
}
}

使用

引入依赖和配置

1
2
3
4
5
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>4.1.0</version>
</dependency>

规则引擎配置

1
2
3
4
5
6
7
8
// 配置规则引擎
RulesEngineParameters parameters = new RulesEngineParameters()
.skipOnFirstAppliedRule(true) // 第一条规则执行后跳过
.skipOnFirstFailedRule(false) // 第一条失败规则后不跳过
.skipOnFirstNonTriggeredRule(false) // 第一条未触发规则后不跳过
.rulePriorityThreshold(10); // 规则优先级阈值

RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

定义多个规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 规则1
@Rule(name = "Adult Rule", description = "检查是否成年", priority = 1)
public class AdultRule {

@Condition
public boolean isAdult(@Fact("age") int age) {
return age >= 18;
}

@Action
public void printAdult() {
System.out.println("已成年,可以进入");
}
}

// 规则2
@Rule(name = "Senior Rule", description = "检查是否是老年人", priority = 2)
public class SeniorRule {

@Condition
public boolean isSenior(@Fact("age") int age) {
return age >= 60;
}

@Action
public void printSenior() {
System.out.println("老年人,享受优惠");
}
}

// 规则3
@Rule(name = "Child Rule", description = "检查是否是儿童", priority = 3)
public class ChildRule {

@Condition
public boolean isChild(@Fact("age") int age) {
return age < 18;
}

@Action
public void printChild() {
System.out.println("未成年人,需要监护人陪同");
}
}

组合使用规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
// 创建规则引擎
RulesEngine rulesEngine = new DefaultRulesEngine();

// 注册规则
Rules rules = new Rules();
rules.register(new AdultRule());
rules.register(new SeniorRule());
rules.register(new ChildRule());

// 准备事实数据
Facts facts = new Facts();
facts.put("age", 25); // 测试不同年龄:15, 25, 65

// 执行规则检查
rulesEngine.fire(rules, facts);
}