规则引擎(Rule Engine)
网关前缀:${API_BASE}/metadata/rules/...
规则引擎用于在元数据层配置可解释、可回放的业务规则,支持将复杂判断逻辑从代码中剥离出来,通过 JSON 谓词树进行描述,并提供在线试跑接口。
后端入口:
- 规则管理:
RuleDefinitionController(/api/v1/rules) - 规则服务:
RuleDefinitionService - 执行引擎:
InMemoryRuleEvaluator
RuleDefinition 结构
规则定义的 DTO:RuleDefinitionDto。
核心字段:
id:规则 IDtenantId:租户 IDname:规则名称(必填)code:规则编码(必填且在租户内唯一)description:规则说明scopeType:作用域类型(枚举RuleDefinition.ScopeType,如业务中约定的invoice、expense等)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:字段为 nullis_not_null:字段非 null
value 的三种形态
比较节点的 value 字段支持:
-
直接字面量:
- 字符串、数字、布尔、数组等,例如:
{ "type": "comparison", "field": "amount", "op": "gt", "value": 1000 } -
字段引用:
{
"type": "comparison",
"field": "invoice.amount",
"op": "gt",
"value": { "type": "field", "path": "policy.single_invoice_max_amount" }
}type: "field":从上下文中按path取值,支持点号分隔。
-
表达式:
{
"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必填且在租户内唯一。name、scopeType必填。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开始pageSize或size:每页大小,默认20sortBy:排序字段,默认createdAtsortDirection:asc/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.evaluateRule 与 InMemoryRuleEvaluator):
- 服务端根据
ruleId或ruleCode加载规则:- 找不到规则,或规则已删除/未启用时,抛出
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_amount、expense_policy_violation),便于日志与审计。 - 建议在业务事件流中使用“规则试跑”模式:
- 首先只记录规则命中与评分,不直接阻断流程;
- 待观察稳定后,再接入实际拦截/告警逻辑。
- 对于频繁变更或高风险规则,推荐结合工作流(Linker)构建“规则发布审批流”和“定期重算/抽检流”,保持治理可控。