当前位置: 首页 > news >正文

风控规则引擎(一):Java 动态脚本

风控规则引擎(一):Java 动态脚本

日常场景

  1. 共享单车会根据微信分或者芝麻分来判断是否交押金
  2. 汽车租赁公司也会根据微信分或者芝麻分来判断是否交押金
  3. 在一些外卖 APP 都会提供根据你的信用等级来发放贷款产品
  4. 金融 APP 中会根据很复杂规则来判断用户是否有借款资格,以及贷款金额。

在简单的场景中,我们可以通过直接编写一些代码来解决需求,比如:

// 判断是否需要支付押金
return 芝麻分 > 650

这种方式代码简单,如果规则简单且不经常变化可以通过这种方式,在业务改变的时候,重新编写代码即可。

在金融场景中,往往会根据不同的产品,不同的时间,对接的银行等等多个维度来配置规则,单纯的直接编写代码无法满足业务需求,而且编写代码的方式对于运营人员来说无论实时性、可视化都很欠缺。

在这种情况往往会引入可视化的规则引擎,允许运营人员可以通过可视化配置的方式来实现一套规则配置,具有实时生效、可视化的效果。减少开发和运营的双重负担。

这篇主要介绍一下如何实现一个可视化的表达式的定义和执行。

表达式的定义

在上面说到的使用场景中,可以了解中至少需要支持布尔表达式。比如

  1. 芝麻分 > 650
  2. 居住地 不在 国外
  3. 年龄在 18 到 60 之间
  4. 名下无其他逾期借款

在上面的例子中,可以将一个表达式分为 3 个部分

  1. 规则参数 (ruleParam)
  2. 对应的操作 (operator)
  3. 对应操作的阈值 (args)

则可以将上面的布尔表达式表示为

  1. 芝麻分 > 650
{"ruleParam": "芝麻分","operator": "大于","args": ["650"]
}
  1. 居住地 不在 国外
{"ruleParam": "居住地","operator": "位于","args": ["国内"]
}
  1. 年龄在 18 到 60 之间
{"ruleParam": "年龄","operator": "区间","args": ["18""60"]
}
  1. 名下无其他逾期借款
{"ruleParam": "在途逾期数量","operator": "等于","args": ["0"]
}

表达式执行

上面的通过将表达式使用 json 格式定义出来,下面就是如何在运行中动态的解析这个 json 格式并执行。

有了 json 格式,可以通过以下方式来执行对应的表达式

  1. 因为表达式的结构已经定义好了,可以通过手写代码来判断所有的情况实现解释执行, 这种方案简单,但增加操作需要修改对应的解释的逻辑, 且性能低
/*
{"ruleParam": "在途逾期数量","operator": "等于","args": ["0"]
}
*/
switch(operator) {case "等于":// 等于操作break;case "大于":// 等于操作break;...
}
  1. 在第一次得到 json 字符串的时候,直接将其根据不同的情况生成对应的 java 代码,并动态编译成 Java Class,方便下一次执行,该方案依然需要处理各种情况,但因为在第一次编译成了 java 代码,性能和直接编写 java 代码一样

  2. 使用第三方库实现表达式的执行

使用第三方库实现动态表达式的执行

在 Java 中有很多表达式引擎,常见的有

  1. jexl3
  2. mvel
  3. spring-expression
  4. QLExpress
  5. groovy
  6. aviator
  7. ognl
  8. fel
  9. jsel

这里简单介绍一下 jexl3 和 aviator 的使用

jexl3 在 apache commons-jexl3 中,该表达式引擎比较符合人的书写习惯,其会判断操作的类型,并将参数转换成对应的类型比如 3 > 4 和 “3” > 4 这两个的执行结果是一样的

aviator 是一个高性能的 Java 的表达式类型,其要求确定参数的类型,比如上面的 “3” > 4 在 aviator 是无法执行的。

jexl3 更适合让运营手动编写的情况,能容忍一些错误情况;aviator 适合开发来使用,使用确定的类型参数来提供性能

jexl3 使用

加入依赖

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-jexl3</artifactId><version>3.2.1</version>
</dependency>
// 创建一个带有缓存 jexl 表达式引擎,
JexlEngine JEXL = new JexlBuilder().cache(1000).strict(true).create();// 根据表达式字符串来创建一个关于年龄的规则
JexlExpression ageExpression = JEXL.createExpression("age > 18 && age < 60");// 获取需要的参数,java 代码太长了,简写一下
Map<String, Object> parameters parameters = {"age": 30}// 执行一下
JexlContext jexlContext = new MapContext(parameters);boolean result = (boolean) executeExpression.evaluate(jexlContext);

以上就会 jexl3 的简单使用

aviator

引入依赖

<dependency><groupId>com.googlecode.aviator</groupId><artifactId>aviator</artifactId><version>5.3.1</version>
</dependency>
Expression ageExpression = executeExpression = AviatorEvaluator.compile("age > 18 && age < 60");// 获取需要的参数,java 代码太长了,简写一下
Map<String, Object> parameters parameters = {"age": 30}boolean result = (boolean) ageExpression.execute(parameters);

注意 aviator 是强类型的,需要注意传入 age 的类型,如果 age 是字符串类型需要进行类型转换

性能测试

不同表达式引擎的性能测试

Benchmark                                         Mode  Cnt           Score           Error  Units
Empty              thrpt    3  1265642062.921 ± 142133136.281  ops/s
Java               thrpt    3    22225354.763 ±  12062844.831  ops/s
JavaClass          thrpt    3    21878714.150 ±   2544279.558  ops/s
JavaDynamicClass   thrpt    3    18911730.698 ±  30559558.758  ops/s
GroovyClass        thrpt    3    10036761.622 ±    184778.709  ops/s
Aviator            thrpt    3     2871064.474 ±   1292098.445  ops/s
Mvel               thrpt    3     2400852.254 ±     12868.642  ops/s
JSEL               thrpt    3     1570590.250 ±     24787.535  ops/s
Jexl               thrpt    3     1121486.972 ±     76890.380  ops/s
OGNL               thrpt    3      776457.762 ±    110618.929  ops/s
QLExpress          thrpt    3      385962.847 ±      3031.776  ops/s
SpEL               thrpt    3      245545.439 ±     11896.161  ops/s
Fel                thrpt    3       21520.546 ±     16429.340  ops/s
GroovyScript       thrpt    3          91.827 ±       106.860  ops/s

总结

这是写的规则引擎的第一篇,主要讲一下

  1. 如何讲一个布尔表达式转换为 json 格式的定义方便做可视化存储和后端校验
  2. 如何去执行一个 json 格式的表达式定义

在这里也提供了一些不同的表达式引擎和性能测试,如果感兴趣的可以去尝试一下。

下一篇主要讲一下在引擎里面规则参数、操作符是如何设计的,也讲一下可视化圆形的设计

相关文章:

风控规则引擎(一):Java 动态脚本

风控规则引擎&#xff08;一&#xff09;&#xff1a;Java 动态脚本 日常场景 共享单车会根据微信分或者芝麻分来判断是否交押金汽车租赁公司也会根据微信分或者芝麻分来判断是否交押金在一些外卖 APP 都会提供根据你的信用等级来发放贷款产品金融 APP 中会根据很复杂规则来判…...

第五十六天|583. 两个字符串的删除操作 72. 编辑距离

583. 两个字符串的删除操作 可以求出最大子序列然后用字符串长度去减&#xff0c;也可以用删除的思路&#xff0c;如下&#xff1a; class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size()1,vector<int…...

java中Lists.newArrayList和new ArrayList的详细区别?

下面是对Lists.newArrayList()和new ArrayList<>()的详细区别进行举例说明&#xff1a; 创建具有初始数据的列表&#xff1a; java Copy code import com.google.common.collect.Lists; List<String> list1 Lists.newArrayList("apple", "banana…...

从图片或PDF文件识别表格提取内容的简单库img2table

img2table是一个基于OpenCV 图像处理的用于 PDF 和图像的表识别和提取 Python库。由于其设计基于神经网络的解决方案&#xff0c;提供了一种实用且更轻便的替代方案&#xff0c;尤其是在 CPU 上使用时。 该库的特点&#xff1a; 识别图像和PDF文件中的表格&#xff0c;包括在表…...

CSV文件中使用insert 函数在指定列循环插入不同数据

文章目录 一、系统、工具要求二、需求三、代码实现&#xff1a;四、核心代码解读五、逐行更改某一列数据六&#xff1a;实现在文件的末尾增加指定内容列 一、系统、工具要求 pandaspythoncsv Windows 系统 二、需求 我有两个文件&#xff1a; 文件一&#xff1a;subject_ma…...

【华为OD题库-064】最小传输时延I-java

题目 某通信网络中有N个网络结点&#xff0c;用1到N进行标识。网络通过一个有向无环图.表示,其中图的边的值表示结点之间的消息传递时延。 现给定相连节点之间的时延列表times[]{u&#xff0c;v&#xff0c; w)&#xff0c;其中u表示源结点&#xff0c;v表示目的结点&#xff0…...

全文检索[ES系列] - 第495篇

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 M…...

【预计IEEE出版|EI征稿通知】第六届下一代数据驱动网络国际学术会议 (NGDN 2024)

第六届下一代数据驱动网络国际学术会议 (NGDN 2024) The Sixth International Conference on Next Generation Data-driven Networks 2024年4月26-28日 | 中国沈阳 基于前几届在英国埃克塞特 (ISPA 2020) 、中国沈阳 (TrustCom 2021) 和中国武汉 (IEEETrustCom-2022) 成功举…...

C++软件在Win平台运行总结

Windows平台&#xff1a; 1.需要安装运行库&#xff1a;无论是exe还是动态库用的哪种平台工具集(visual2010-visual2019)进行编译&#xff0c;需要安装对应的运行时库vc_redist.x64.exe/vc_redist.x86.exe。比如Exe用的是VisualStdio2010工具集编译&#xff0c;其中链接的一个…...

【数电笔记】16-卡诺图绘制(逻辑函数的卡诺图化简)

目录 说明&#xff1a; 最小项卡诺图的组成 1. 相邻最小项 2. 卡诺图的组成 2.1 二变量卡诺图 2.2 三表变量卡诺图 2.3 四变量卡诺图 3. 卡诺图中的相邻项&#xff08;几何相邻&#xff09; 说明&#xff1a; 笔记配套视频来源&#xff1a;B站&#xff1b;本系列笔记并…...

前端面试灵魂提问(1)

1.自我介绍 2.在实习中&#xff0c;你负责那一模块 3.any与unknow的异同 相同点&#xff1a;any和unkonwn 可以接受任何值 不同点&#xff1a;any会丢掉类型限制&#xff0c;可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查&#xff0c;所以在使用一个…...

Linux中项目部署步骤

安装jdk&#xff0c;tomcat 安装步骤 1&#xff0c;将压缩包&#xff0c;拷贝到虚拟机中。 通过工具&#xff0c;将文件直接拖到虚拟机的/home下 2&#xff0c;回到虚拟机中&#xff0c;查看/home下&#xff0c;有两个压缩文件 3&#xff0c;给压缩文件做解压缩操作 tar -z…...

cmd下查看python命令的用法

在cmd下&#xff0c;可以运行python --help或者py --help来查看python命令的用法。例如&#xff1a;...

大型语言模型在实体关系提取中的应用探索(二)

上一篇文章我们探讨了如何使用大语言模型进行实体关系的抽取。本篇文章我们将进一步探索这个话题。比较一下国内外几款知名大模型在相同的实体关系提取任务下的表现。由于精力有限&#xff0c;我们无法全面测试各模型的实体关系抽取能力&#xff0c;因此&#xff0c;看到的效果…...

Easy Excel设置表格样式

1. 设置通用样式 import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.xxx.npi.config.easypoi.EasyExcelDateConverter; import lombok.Data; import …...

HarmonyOS/OpenHarmony应用开发

OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目, 目标是面向全场景、全连接、全智能时代, 搭建一个智能终端设备操作系统的框架和平台, 促进万物互联产业的繁荣发展。 了解OpenHarmony HarmonyOS是华为通过OpenHarmony项目&#xff0c;结合商业…...

孩子都能学会的FPGA:第二十一课——用线性反馈移位寄存器实现伪随机序列

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…...

国内 AI 成图第一案!你来你会怎么判?

我国目前并未出台专门针对网络爬虫技术的法律规范&#xff0c;但在司法实践中&#xff0c;相关判决已屡见不鲜&#xff0c;K 哥特设了“K哥爬虫普法”专栏&#xff0c;本栏目通过对真实案例的分析&#xff0c;旨在提高广大爬虫工程师的法律意识&#xff0c;知晓如何合法合规利用…...

快速登录界面关于如何登录以及多账号列表解析以及config配置文件是如何读取(1)

快速登录界面关于如何登录以及多账号列表解析以及config配置文件是如何读取 1、快速登录界面关于如何登录以及快速登录界面账号如何显示 如图所示:根据按下按钮一键登录中途会发生什么。 关于一键登录按钮皮肤skin的设置: <Button name"QuickLoginOkBtn" text&q…...

finebi 新手入门案例

finebi 新手入门案例 连锁超市销售数据分析 步骤&#xff1a; 准备公共数据新建分析主题处理数据在数据中分析在图形中分析数据大屏 准备公共数据 点击公共数据 点击新建文件夹 修改文件夹名称 上传数据 鼠标悬停在文件夹上&#xff0c;右侧出现 鼠标悬停在文件夹上&#x…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...