跳到主要内容

规则引擎(Rule Engine)

网关前缀:${API_BASE}/metadata/rules/...

规则引擎用于在元数据层配置可解释、可回放的业务规则,支持将复杂判断逻辑从代码中剥离出来,通过 JSON 谓词树进行描述,并提供在线试跑接口。

后端入口:

  • 规则管理:RuleDefinitionController/api/v1/rules
  • 规则服务:RuleDefinitionService
  • 执行引擎:InMemoryRuleEvaluator

RuleDefinition 结构

规则定义的 DTO:RuleDefinitionDto

核心字段:

  • id:规则 ID
  • tenantId:租户 ID
  • name:规则名称(必填)
  • code:规则编码(必填且在租户内唯一)
  • description:规则说明
  • scopeType:作用域类型(枚举 RuleDefinition.ScopeType,如业务中约定的 invoiceexpense 等)
  • scopeKey:作用域键(可选,用于进一步限定规则适用范围)
  • predicate:规则谓词树(JSON,见下一节)
  • enabled:是否启用(控制是否允许执行)
  • createdAt / updatedAt:时间
  • createdBy / updatedBy:审计字段

规则引擎本身只负责“条件判断 + 命中路径”,具体命中后的评分、风险等级、处置动作等由上层业务负责。

谓词模型(Predicate)

谓词模型统一由 com.aidaas.common.predicate.Predicate 表达,支持三类节点:

  • 逻辑节点(type = "logical"
  • 取反节点(type = "not"
  • 比较节点(type = "comparison",默认类型)

逻辑节点(LogicalPredicate)

结构:

{
"type": "logical",
"op": "and",
"conditions": [
{ "type": "comparison", "field": "amount", "op": "gt", "value": 1000 },
{ "type": "comparison", "field": "status", "op": "eq", "value": "PAID" }
]
}

字段:

  • type: 固定为 "logical"
  • op: 逻辑操作符,取值:
    • "and":所有子条件为 true 才通过
    • "or":任一子条件为 true 即通过
  • conditions: 子谓词数组(可以继续嵌套 logical/not/comparison

空条件数组的处理:

  • 对于 and:视为 true
  • 对于 or:视为 false

取反节点(NotPredicate)

结构:

{
"type": "not",
"op": "not",
"condition": {
"type": "comparison",
"field": "currency",
"op": "eq",
"value": "CNY"
}
}

字段:

  • type: 固定为 "not"
  • op: 固定为 "not"(与数据服务侧保持一致)
  • condition: 内部要取反的谓词

比较节点(ComparisonPredicate)

结构:

{
"type": "comparison",
"field": "amount",
"op": "gte",
"value": 1000
}

字段:

  • type: "comparison" 或省略(缺省时也会按比较节点处理)
  • field: 字段路径,使用点号分隔(如 "invoice.amount""amount"
  • op: 比较操作符(见下)
  • value: 比较右值,支持多种形态(字面量 / 列表 / 特殊对象)

比较操作符枚举(ComparisonOperator):

  • 相等与不等:
    • eq:等于
    • ne:不等于
  • 大小比较:
    • gt:大于
    • gte:大于等于
    • lt:小于
    • lte:小于等于
  • 集合:
    • in:属于集合中的任一元素
    • not_in:不属于集合中的任何元素
  • 模糊匹配:
    • like:大小写敏感,% 为通配
    • ilike:大小写不敏感
  • 区间:
    • between:在区间内,value 为长度为 2 的数组 [min, max]
  • 空值判断:
    • is_null:字段为 null
    • is_not_null:字段非 null

value 的三种形态

比较节点的 value 字段支持:

  1. 直接字面量:

    • 字符串、数字、布尔、数组等,例如:
    { "type": "comparison", "field": "amount", "op": "gt", "value": 1000 }
  2. 字段引用:

    {
    "type": "comparison",
    "field": "invoice.amount",
    "op": "gt",
    "value": { "type": "field", "path": "policy.single_invoice_max_amount" }
    }
    • type: "field":从上下文中按 path 取值,支持点号分隔。
  3. 表达式:

    {
    "type": "comparison",
    "field": "amount_excl_tax",
    "op": "gt",
    "value": { "type": "expression", "expr": "policy.sensitive_amount_min * 1.1" }
    }
    • type: "expression":使用 Spring SpEL 表达式,context 作为 root map,且同名 key 也会作为变量注入。
    • 表达式异常时会返回 null,整体比较按 null 处理。

规则管理 API

基础路径:/metadata/rules(网关映射到 /api/v1/rules)。

权限:tenant:admin / admin

请求头:

  • Authorization: Bearer <token>
  • X-Tenant-Id: <tenantId>

批量创建规则

  • POST /metadata/rules/batch

请求体:RuleDefinitionDto[]

说明:

  • 服务端会为当前租户逐条创建规则,校验 code 唯一性与 predicate 合法性。

单条创建规则

  • POST /metadata/rules

示例:

curl -X POST "${API_BASE}/metadata/rules" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Id: tenant-abc123" \
-H "Content-Type: application/json" \
-d '{
"code": "invoice_high_amount",
"name": "大额发票告警",
"description": "单张发票金额超过 1w 的告警规则",
"scopeType": "invoice",
"scopeKey": null,
"predicate": {
"type": "comparison",
"field": "invoice.amount",
"op": "gt",
"value": 10000
},
"enabled": true
}'

校验规则(见 RuleDefinitionService.createRule):

  • code 必填且在租户内唯一。
  • namescopeType 必填。
  • predicate 必填且必须能序列化为合法 JSON(否则报错 Invalid predicate)。

更新规则

  • PUT /metadata/rules/{id}

说明:

  • 若请求体中包含 predicate,会重新校验其合法性。
  • 其它字段按 DTO 进行覆盖更新。

删除规则

  • DELETE /metadata/rules/{id}

说明:

  • 内部为软删除(deleted = true),后续查询与执行不再返回、使用该规则。

按 ID 查询规则

  • GET /metadata/rules/{id}

返回单个 RuleDefinitionDto,若不存在则返回错误响应。

分页查询规则

  • GET /metadata/rules?page=1&pageSize=20&sortBy=createdAt&sortDirection=desc

请求参数:

  • page:页号,从 1 开始
  • pageSizesize:每页大小,默认 20
  • sortBy:排序字段,默认 createdAt
  • sortDirectionasc / desc,默认 desc

响应为 PageResponse<RuleDefinitionDto>

规则评估(试跑接口)

评估接口:

  • POST /metadata/rules/evaluate

请求体:RuleEvaluationRequest,核心字段:

  • ruleId:规则 ID(二选一)
  • ruleCode:规则编码(二选一)
  • context:上下文对象 Map<String,Object>,用于提供字段值与表达式变量

示例:

curl -X POST "${API_BASE}/metadata/rules/evaluate" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Id: tenant-abc123" \
-H "Content-Type: application/json" \
-d '{
"ruleCode": "invoice_high_amount",
"context": {
"invoice": { "amount": 12000, "currency": "CNY" },
"policy": { "single_invoice_max_amount": 10000 }
}
}'

行为说明(见 RuleDefinitionService.evaluateRuleInMemoryRuleEvaluator):

  • 服务端根据 ruleIdruleCode 加载规则:
    • 找不到规则,或规则已删除/未启用时,抛出 Rule not available for evaluation
  • 将规则的 predicate 解析为 Predicate 对象并执行。

返回体:RuleEvaluationResult,核心字段:

  • result:整体规则是否通过(布尔)
  • matchedPaths:命中路径列表
  • failedPaths:失败路径列表

路径语义:

  • 逻辑节点:使用数组索引路径表示,例如:
    • 根节点:""(空字符串)
    • 第一层子节点:"0""1"
    • 嵌套路径:"0.1""1.2"
  • 比较节点:优先使用 field 作为路径(例如 "invoice.amount"),便于排查。

前端规则编辑与 Dry-run(参考)

前端内置了规则编辑器与 dry-run 工具(/ui/web/src/ruleengine),主要类型见 ruleTypes.ts

  • 支持按实体与字段可视化选择(如 fin_invoice.amount
  • 提供操作符选择、值输入(字面量 / 表达式 / 字段引用)
  • 提供预置表达式(如时间窗口、行为指标等)

这层 UI 会生成与 Predicate 模型兼容的 JSON,提交到上述规则管理与评估接口。

使用建议

  • 将规则编码 code 设计为稳定且可读的标识(如 invoice_high_amountexpense_policy_violation),便于日志与审计。
  • 建议在业务事件流中使用“规则试跑”模式:
    • 首先只记录规则命中与评分,不直接阻断流程;
    • 待观察稳定后,再接入实际拦截/告警逻辑。
  • 对于频繁变更或高风险规则,推荐结合工作流(Linker)构建“规则发布审批流”和“定期重算/抽检流”,保持治理可控。