背景:做金融业务都会涉及到数据校验,之前是银行统一给excel文件,我们按照统一格式将数据填充,并进行校验数据。因涉密无法查看具体校验宏脚本,但可以查看到数据校验规则。
- Jvm 解析表达式
Java 有类似的处理程序例如,System.out.println(),会将你传进去的表达式解析成你想要的结果,例如:
System.out.println(5>2);===>true
System.out.println(5>2&3<2-1);====>false
因为自己地盘不稳,无法将源码功能提取出来,只能自己手动书写。刚开始采用 ScriptEngineManager 去做数据处理,以及逻辑表达式的校验,但是数字计算过程中会有精度丢失类似Java 中double的精度丢失。具体请看链接 Js 计算精度之谜
- 解决思路
- 按照规则去预加载的数据缓存中加载数据(本文省略)
- 解析已经填充数据的表达式,包含加减、逻辑计算。例如:226975869075.79-224645619456.84>=0 & null -0.1> 1,不要问我为啥有null。
- 将表达式按照逻辑计算符号切割,并将切割后的值去做计算四则运算,将计算后的结果返回。
- 得到返回结果的表达式,将会是两个逻辑计算符号的比较
- 再利用ScriptEngineManager去比较逻辑表达式是否正确。
- 具体实现
- ScriptEngineManager 解析工具类,用来解析两个逻辑判断是否成立。
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; /** * @author wangxiao * @description: //TODO ScriptEngine 比较表达式 * @date 2019/11/5 */ public class ScriptEngineUtil { private static String ONE = "1"; private static String ZERO = "0"; private static String EVAL_RESULT; private static ScriptEngineManager manager; private static ScriptEngine engine; static { manager = new ScriptEngineManager(); engine = manager.getEngineByName("JavaScript"); } private ScriptEngineUtil (){} public static String calcExpr(String expr)throws Exception{ EVAL_RESULT = engine.eval(expr).toString(); if (ZERO.equals(EVAL_RESULT)){ return Boolean.FALSE.toString(); }else if (ONE.equals(EVAL_RESULT)) { return Boolean.TRUE.toString(); }else { return EVAL_RESULT; } } }
- 计算四则运算工具类,用来计算四则运算的结果。在计算表达式中null 默认是0.00
import org.apache.commons.lang.StringUtils; import org.springframework.util.Assert; import java.math.BigDecimal; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.sykzx.daex.valid.utils.calculate.CalculateUtil.ZERO_STR; /** * @author wangxiao * @description: //计算运算字符串表达式的结果 如果出现null 则替换成0 * @date 2019/11/5 */ public class ComputeUtil { static String ADD = "+"; static String MUL = "*"; static String ZERO_FOUR ="0.0000"; private static String SIGS = "+-*/"; private static String ADD_OR_SUB ="\\+|\\-"; private static String MUL_OR_DIV ="\\*|\\/"; private static Pattern PATTERN_ALL_COM = Pattern.compile("\\d+[.]?\\d*[\\+|\\-|\\*|\\/]\\d+[.]?\\d*"); private static Patt