欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 规则引擎aviatorEvaluator注意点

规则引擎aviatorEvaluator注意点

2024/11/30 13:30:49 来源:https://blog.csdn.net/qq_32647655/article/details/143999665  浏览:    关键词:规则引擎aviatorEvaluator注意点

规则引擎aviatorEvaluator注意点

官方文档:AviatorScript 编程指南(5.0) · 语雀

1、依赖

        <!--规则引擎--><dependency><groupId>com.googlecode.aviator</groupId><artifactId>aviator</artifactId><version>5.4.3</version></dependency>

2、自定义函数

package com.jayce.boot.route.common.aviatorEvaluator;import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorObject;import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;public class RoundFunction extends AbstractFunction {private static final long serialVersionUID = 1;@Overridepublic AviatorObject call(final Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {Number number = FunctionUtils.getNumberValue(arg1, env);Number number2 = FunctionUtils.getNumberValue(arg2, env);BigDecimal numberData = new BigDecimal(number.toString());// 四舍五入BigDecimal roundedHalfUp = numberData.setScale(number2.intValue(), RoundingMode.HALF_UP);return AviatorDecimal.valueOf(roundedHalfUp);}@Overridepublic String getName() {return "ROUND";}
}

使用时:

String expression = "ROUND((task_a + task_b) - (task_c/task_d) + task_a*task_c,2)";

Expression compiledExp = AviatorEvaluator.getInstance().compile(expression);

Expression compiledExp = instance.compile(expression);

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("task_a", 3.666666666666666);
paramMap.put("task_b", 7);
paramMap.put("task_c", 1);
paramMap.put("task_d", 2);

Object result = compiledExp.execute(paramMap);

3、关于计算精度问题

// -- 1. 解析浮点数为 Decimal 类型
AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();
instance.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
// -- 2. 解析整数为 Decimal 类型
instance.setOption(Options.ALWAYS_PARSE_INTEGRAL_NUMBER_INTO_DECIMAL, true);

4、除法变量替换表达式存在bug


如:String expression = "1/2";    result = 0.5;

a=1,b=2;

String expression = "a/b";  result = 0;

得出结果不一样,底层处理可能存在计算漏洞。

临时解决办法,先自行定义规则进行替换,再直接数字直接运算

替换方法:

/*** 替换字符串表达式中的变量为map中对应的值。** @param expression 包含变量的数学表达式* @param values     存储变量及其值的映射* @return 替换后的数学表达式*/public static String replaceVariables(String expression, Map<String, Object> values) {// 正则表达式用于匹配变量名//正则表达式:\\b[a-zA-Z_][a-zA-Z0-9_]*\\b 用于匹配变量名。这里的 \b 是单词边界,确保我们只匹配完整的变量名,而不是部分字符串Pattern pattern = Pattern.compile("\\b[a-zA-Z_][a-zA-Z0-9_]*\\b");Matcher matcher = pattern.matcher(expression);StringBuffer sb = new StringBuffer();while (matcher.find()) {String variable = matcher.group(); // 获取匹配到的变量名if (values.containsKey(variable)) {String replacement = String.valueOf(values.get(variable));// 使用找到的值替换变量matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));} else {// 如果变量不在map中,保留原样matcher.appendReplacement(sb, Matcher.quoteReplacement(variable));}}matcher.appendTail(sb);return sb.toString();}

使用示例:
String expression = "ROUND((task_a + task_b) - (task_c/task_d) + task_a*task_c,2)";

Map<String, Object> paramMap = new HashMap<>();

变量赋值............
//计算逻辑手动替换,自动替换有bug,除法丢精度
expression = replaceVariables(expression, paramMap);

//参数无需传入

Object result = xxx.execute();

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com