一种基于 JEP 和可配置公式实现用户自定义字段的解决方案
一、 简介
A: 介绍
-
JEP(Java Expression Parser)
-
用于解析和计算表达式,核心功能就是计算公式的解析和结果的计算。
-
在JEP 2.4.1版本之前未符合GPLv3 协议的免费开源包。
-
JEP 支持用户自定义函数、常量、变量,在JEP中已经包含了大量可使用的通用数学公式和常量,可以满足绝大多数的数学计算需求
-
官方地址: http://www.singularsys.com/jep/,在官网上可以下载使用版本和相关文档
-
或使用Maven 添加依赖
<!-- https://mvnrepository.com/artifact/jep/jep --> <dependency> <groupId>jep</groupId> <artifactId>jep</artifactId> <version>2.24</version> </dependency>
-
JEP特性:
- 文件小巧(jar包在300K以下)
- 快速计算
- 求值精度高,在计算过程中使用BigDecimal
- 已经内含了常用的数学函数和运算符
- 支持布尔型表达式
- 具有良好的可扩展性和可配置性
- 支持字符串、向量、复杂数值
- 支持隐式乘法
- 允许声明或者未声明的变量
- 最低兼容Java1.5
- 支持Unicode字符
- 有大量的参考文档
- 包含JavaCC语法分析生成器可自动生成main class
B: 实例
- JEP 对一个表达式的计算包含两个步骤
- JEP 首先会对表达式进行解析,解析后会生成一个树形结构,接下来会基于这个树形结构进行快速求值
-
从上图的工作流程可以看出,JEP的工作流程非常简单。 实例:
/** * String expression = "(x+y)*n/z"; * @desc 简单实例 */ private static void demo1(String expression) { JEP jep = new JEP(); try { // 设置表达式中变量的值 jep.addVariable("x", 1); jep.addVariable("y", 100); jep.addVariable("n", 100); jep.addVariable("z", 2); // 载入并解析表达式 jep.parseExpression(expression); // 获取计算结果 double value = jep.getValue(); // 输出结果 String result = new String(expression); result = result.replace("x", "1"); result = result.replace("y", "100"); result = result.replace("n", "100"); result = result.replace("z", "2"); result += "=" + value; System.out.println("计算结果 --> " + result); } catch (Exception e) { e.printStackTrace(); } } 输出结果: 计算结果 --> (1+100)*100/2=5050.0
-
- JEP 首先会对表达式进行解析,解析后会生成一个树形结构,接下来会基于这个树形结构进行快速求值
二、 整体设计说明
- JEP 的整体设计
- 在JEP 的设计方案中 , JEP 提供了一套用于对数学表达式解析和计算的类库 , 可以对用户配置的计算公式进行解析 , 并且快速求值。 通过将计算公式设计拥有将用户隔离、配置化管理以及运行时载入三个特性,我们可以对同一字段针对不同的用户配置不同的计算公式。
A:JEP
- JEP为整个功能设计的核心,主要对公式进行读取和解析,并为计算中遇到的变量进行赋值,并且计算结果
B: 可配置化公式
- 按用户隔离
- 每一个用户都使用独立文件存放计算公式,用户之间不会相互干扰,实现用户公式的个性化配置。
- 配置化管理
- 提供修改功能,保持程序的灵活性和可扩展性。在新增自定义字段或者改变计算公式时,无需修改代码,只需要重新对计算公式进行配置即可。
- 运行时载入
- 修改配置后,无需重启应用,也可将配置的公式载入运行时的系统中
- 在系统启动时会读取配置文件,在系统运行过程中,提供对用户的自定义公式的再配置功能并重新加载,在无需重启服务器的情况下让新配置的公式生效
三、 总结
- 本文对第三方Java类库JEP做了一个简单的入门介绍。