摘要

规则引擎的内置函数库无法覆盖所有业务场景——金融场景的LPR利率计算、电商场景的复杂促销叠加、政企场景的特定数据脱敏规则,都需要开发者自行扩展函数能力。本文以支持全量源码交付的JVS-Rules规则引擎为例,从源码结构、函数注册机制、Groovy动态加载原理到完整实战案例进行全链路解析,手把手演示如何扩展一个自定义规则函数并实现热加载。

1. 为什么需要自定义规则函数

JVS-Rules内置了八大类函数——脱敏函数、对象函数、数学函数、时间函数、转换函数、集合函数、文字函数、逻辑函数——覆盖了90%的通用场景。但企业级应用总有特殊需求:

  • 行业特有计算:如金融LPR浮动利率计算、制造业工时费计算

  • 复杂业务逻辑:如电商“满减+会员折扣+品类优惠”多条件叠加计算

  • 外部系统集成:如调用第三方风控API、查询实时汇率

  • 定制数据脱敏:如特定格式的证件号、银行卡号脱敏规则

当内置函数不够用时,具备源码交付能力的规则引擎允许开发者自行扩展。JVS-Rules采用 Spring Cloud + VUE 技术架构,支持全量源码二次开发。

2. 源码结构解析

JVS-Rules的函数管理相关核心模块如下:

text

jvs-rules/
├── jvs-rules-core/                  # 核心引擎
│   ├── src/main/java/
│   │   ├── com.jvs.rules.engine/    # 规则引擎执行器
│   │   ├── com.jvs.rules.function/  # 函数管理
│   │   │   ├── FunctionRepository   # 函数仓库
│   │   │   ├── FunctionRegistry     # 函数注册器
│   │   │   └── builtin/             # 内置函数实现
│   │   │       ├── MathFunctions    # 数学函数
│   │   │       ├── DateFunctions    # 时间函数
│   │   │       └── ...
│   │   └── com.jvs.rules.parser/    # 规则解析器
├── jvs-rules-web/                   # Web管理端
│   └── src/main/
│       ├── java/                    # 后端API
│       └── resources/               # 前端资源
└── jvs-rules-api/                   # API定义

关键类说明

  • FunctionRepository:函数仓库,管理所有已注册函数的生命周期。

  • FunctionRegistry:函数注册器,支持动态注册和卸载自定义函数。

  • builtin/:内置函数实现,每个函数对应一个Java方法,通过注解标记。

3. 自定义函数的实现机制

JVS-Rules的函数扩展基于Groovy动态语言。函数体可以使用Groovy原生语法,也可以调用Java工具类。

所有函数存储在数据库表 jvs_function_base 中:

sql

CREATE TABLE `jvs_function_base` (
  `name` varchar(64) NOT NULL COMMENT '函数名称',
  `type` varchar(32) NOT NULL COMMENT '函数分类',
  `info` text COMMENT '函数描述',
  `param_count` varchar(10) COMMENT '参数数量',
  `dynamic_param` tinyint DEFAULT 0 COMMENT '是否动态参数',
  `enable_cache` tinyint DEFAULT 1 COMMENT '是否启用缓存',
  `jvs_param_type` varchar(32) DEFAULT 'any' COMMENT '参数类型',
  `body` text COMMENT '函数体(Groovy代码)'
);

函数注册流程

  1. 在Web管理端点击“新增函数”,填写函数名称、分类、描述

  2. 指定参数个数和参数类型

  3. 编写函数体(Groovy代码)

  4. 点击“测试”验证函数正确性

  5. 保存后,在“运维设置”中点击“更新”重新加载缓存

4. 实战:扩展一个自定义函数

以金融风控场景的“计算LPR浮动利率”为例,演示完整的自定义函数扩展过程。

场景描述:风控规则中需要根据贷款金额和期限计算基于LPR(贷款市场报价利率)的浮动利率。LPR值需从外部API实时获取。

方案一:纯Groovy脚本扩展(适合简单逻辑)

在Web管理端的函数新增界面中填写:

  • 函数名称calcLprRate

  • 分类数学函数

  • 参数个数2(贷款金额、贷款期限)

  • 函数体

groovy

// 使用Groovy语法实现LPR利率计算
import java.time.LocalDate

// 模拟LPR查询(实际项目可调用外部API)
def getCurrentLpr() {
    // 简化示例:1年期LPR固定值3.45%
    return 3.45
}

def baseLpr = getCurrentLpr()
def amount = params[0] as double
def term = params[1] as int

// 金额加成:超过100万加0.2%
def amountPremium = amount > 1000000 ? 0.2 : 0
// 期限加成:超过5年加0.3%
def termPremium = term > 5 ? 0.3 : 0

return baseLpr + amountPremium + termPremium

方案二:调用Java工具类扩展(适合复杂逻辑)

先在Java源码中编写工具类:

java

package com.jvs.rules.custom;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LprCalculator {
    private static final HttpClient client = HttpClient.newHttpClient();
    
    public static double getLprRate(double amount, int term) {
        double baseLpr = fetchLprFromApi();
        double amountPremium = amount > 1000000 ? 0.2 : 0;
        double termPremium = term > 5 ? 0.3 : 0;
        return baseLpr + amountPremium + termPremium;
    }
    
    private static double fetchLprFromApi() {
        // HTTP调用央行LPR查询接口
        // 返回当前LPR值
    }
}

然后在函数体中导入并调用:

groovy

import com.jvs.rules.custom.LprCalculator

def amount = params[0] as double
def term = params[1] as int
return LprCalculator.getLprRate(amount, term)

方案三:动态参数函数

如果需要支持任意数量的参数(如求和、求平均),配置动态参数即可:

groovy

// 动态参数函数:支持任意数量的数字求和
// param_count: [0], dynamic_param: 1
import cn.hutool.core.util.NumberUtil

def sum = 0
for (int i = 0; i < params.size(); i++) {
    def val = params[i]
    if (val instanceof String) {
        val = NumberUtil.parseNumber(val as String)
    }
    sum = NumberUtil.add((Number) val, (Number) sum)
}
return sum

5. 热加载机制解析

JVS-Rules的自定义函数支持热加载——修改后无需重启应用即可生效:

  1. 函数体存储在数据库中,修改后点击保存

  2. 系统检测到变更,触发GroovyClassLoader重新编译

  3. 编译后的函数实例替换内存中的旧实例

  4. 后续规则调用自动使用新函数,全程对业务无感知

6. 扩展建议与最佳实践

1. 善用工具库:JVS-Rules默认集成了Hutool工具类,可直接调用 cn.hutool.core.util.* 下的工具方法。

2. 注意参数类型校验:函数参数可能来自规则配置界面的不同输入,建议在函数体中进行类型转换和空值判断。

3. 启用缓存提升性能:对于计算开销大的函数(如外部API调用),开启 enable_cache 可显著提升性能。

4. 编写清晰的函数描述:使用HTML标签格式化 info 字段描述,方便其他开发者理解和使用。

7. 总结

JVS-Rules的自定义函数扩展机制基于 Groovy动态语言 + 数据库存储 + 热加载,开发者无需修改核心引擎代码即可扩展新的规则函数。核心价值在于灵活扩展、一次编写多规则共享、按需定制高性能算法。对于金融风控、电商促销、行业规则计算等场景,这一能力大幅降低了规则引擎的定制门槛。

本文为技术实践分享,基于JVS-Rules开源版本编写。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐