- ExpressionEvaluator:Aviator 5.4.3 沙箱(FEATURE_SET 只留 If、ALLOWED_CLASS_SET 空=禁类访问/反射)、编译缓存、 顶层变量缺失抛错挂起(Aviator 缺失变量按 nil 且 nil 视作最小值,<= 兜底出口会静默放行——宁挂起不误放行) - ConditionRouteService.decide 分流:EXPRESSION 按出边顺序取首个 true(逐边结果摘要落 raw_response), 全 false/异常挂起沿用 SERVICE 纪律(route_log outlet=NULL + EXPRESSION 常量 + 告警 + 管理端重跑) - DefValidator 发布期分层校验:EXPRESSION 出口缺条件/语法错/违禁表达式硬拦;表单变量放行(运行时核对); 内置变量疑似拼错 warn;judgeMode 非法值拦 - /admin/router/eval 调试端点(同一求值核心,不落库不走流程) - 单测 22 新增 + 全量 170 绿;E2E 18/18(发布/分支选路/挂起留痕/重跑/调试)见 local-debug/four-topics-a-e2e.py
73 lines
3.6 KiB
Java
73 lines
3.6 KiB
Java
package com.yunhai.flowcenter.engine;
|
||
|
||
import com.googlecode.aviator.AviatorEvaluator;
|
||
import com.googlecode.aviator.AviatorEvaluatorInstance;
|
||
import com.googlecode.aviator.Expression;
|
||
import com.googlecode.aviator.Feature;
|
||
import com.googlecode.aviator.Options;
|
||
|
||
import java.util.Collections;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 条件路由表达式求值核心(2026-10-10 四议题 Phase 4):CONDITION 节点 judgeMode=EXPRESSION 时,
|
||
* 出边 condition 即 AviatorScript 表达式,按出边定义顺序取首个求值为 true 的出口。
|
||
* 发布期校验(DefValidator)、运行时(ConditionRouteService)、调试端点(/admin/router/eval)
|
||
* 共用本类——三处口径天然一致。
|
||
*
|
||
* <p><b>沙箱纪律(勿放宽)</b>:FEATURE_SET 只留 If(三元/条件),NewInstance/Module/Use/
|
||
* Static* 全部不在集合内即禁用;ALLOWED_CLASS_SET=空不可变集 = 禁一切 Java 类访问(反射/静态
|
||
* 方法/类字面量);表达式只能引用变量与 Aviator 内置纯函数(math/string/seq)。
|
||
*
|
||
* <p><b>缺失变量口径(宁挂起不误放行)</b>:顶层变量缺失(拼写错/表单未传)直接抛错由调用方
|
||
* 挂起——Aviator 的 nil 参与大小比较时视作最小值,{@code x <= n} 这类兜底出口会对缺失字段
|
||
* <i>静默放行</i>,必须拦住。判空请显式写 {@code x == nil}(嵌套属性缺失走 nil 语义,
|
||
* {@code form.amount == nil} 可用)。env 中显式为 null 的值仍按 nil 语义求值。
|
||
*
|
||
* <p>线程安全:{@link AviatorEvaluatorInstance} 本身线程安全,编译结果带缓存(key=表达式串)。
|
||
*/
|
||
public final class ExpressionEvaluator {
|
||
|
||
private ExpressionEvaluator() {
|
||
}
|
||
|
||
private static final AviatorEvaluatorInstance INSTANCE = createSandboxed();
|
||
|
||
private static AviatorEvaluatorInstance createSandboxed() {
|
||
AviatorEvaluatorInstance instance = AviatorEvaluator.newInstance();
|
||
instance.setOption(Options.FEATURE_SET, Feature.asSet(Feature.If));
|
||
instance.setOption(Options.ALLOWED_CLASS_SET, Collections.emptySet());
|
||
instance.setOption(Options.NIL_WHEN_PROPERTY_NOT_FOUND, Boolean.TRUE);
|
||
return instance;
|
||
}
|
||
|
||
/**
|
||
* 求值(编译缓存复用)。顶层变量缺失直接抛错(调用方挂起)——Aviator 对缺失顶层变量一律
|
||
* 按 nil 求值且不可配置,而 nil 视作最小值会让 {@code x <= n} 这类兜底出口静默放行。
|
||
* 嵌套属性(form.amount)缺失走 nil 语义,判空请显式 {@code form.amount == nil}。
|
||
*
|
||
* @return 求值结果;调用方仅把 Boolean.TRUE 视为命中(null/非布尔一律不命中——宁挂起不误放行)
|
||
*/
|
||
public static Object evaluate(String expression, Map<String, Object> env) {
|
||
Expression compiled = compile(expression);
|
||
for (String name : compiled.getVariableNames()) {
|
||
if (!env.containsKey(name)) {
|
||
throw new IllegalStateException("表达式变量未提供:" + name
|
||
+ "(拼写错误或表单未传;宁挂起不误放行,不按 nil 求值)");
|
||
}
|
||
}
|
||
return compiled.execute(env);
|
||
}
|
||
|
||
/** 语法校验/预编译(发布期拦语法错;与运行时走同一编译路径) */
|
||
public static Expression compile(String expression) {
|
||
return INSTANCE.compile(expression, true);
|
||
}
|
||
|
||
/** 表达式引用的顶层变量名(发布期"内置变量疑似拼错"提示用) */
|
||
public static List<String> variableNames(String expression) {
|
||
return compile(expression).getVariableNames();
|
||
}
|
||
}
|