摘要纯Java零依赖自定义表达式解析方案摘要还在靠if/else硬编码实现业务动态规则改规则必发版、脚本引擎有安全漏洞、重型规则引擎接入成本过高是多数开发者的共性难题本文手把手落地一套轻量无冗余、杜绝脚本注入风险支持嵌套条件、多元运算与JSON解析可配置、可动态刷新轻松根治项目动态规则开发痛点。关键词Java 轻量级表达式引擎、自定义表达式解析、动态业务规则、Java 规则引擎业务痛点if else 硬编码优化、动态规则不用频繁发版、避免脚本注入漏洞、替代 Drools 重型规则引擎、SpEL 安全风险、业务规则配置化一、前言在日常业务开发中我们经常需要处理大量动态条件规则典型场景包含风控规则配置、用户画像筛选、日志过滤、流程分支判断、自定义表单校验等高频业务需求。传统Java开发实现这类需求普遍存在非常明显的技术痛点也是绝大多数项目的共性难题硬编码臃肿大量 if/else、多层嵌套判断代码可读性极差维护成本极高长期迭代极易形成烂代码堆积改规则必发版微小业务规则变动都需要修改代码、打包部署、重启服务迭代效率极低开源方案弊端明显传统重型规则引擎Drools笨重复杂、学习成本高、接入繁琐常用脚本工具SpEL存在脚本注入安全风险生产环境隐患极大针对以上行业通用痛点本文带大家从零落地一套纯Java、零重型依赖、高安全、可生产落地的自定义表达式解析方案自研轻量级规则引擎完美替代传统硬编码与重型规则框架轻松实现业务规则配置化彻底摆脱改规则必发版的开发困境。二、引擎核心能力与优势核心能力这款自研轻量级Java表达式解析引擎覆盖绝大多数业务场景所需的解析能力功能全面、开箱即用完美适配各类动态规则开发需求支持多层括号嵌套完美解析复杂组合条件适配各类复杂业务判断覆盖全量常规运算数值大小比对、等值判断、不等判断满足基础数值逻辑支持全方位字符串匹配包含、不包含、模糊匹配适配文本类规则筛选支持AND、OR多逻辑混合嵌套运算灵活组合多元业务规则高阶核心能力JSON表达式解析、JSON数组匹配、数组长度校验、字段非空校验适配复杂JSON结构化数据解析内置表达式语法预校验能力可前置拦截非法表达式避免上线报错全局异常容错机制兼容空数据、脏数据、非法表达式杜绝程序异常崩溃核心优势对比 Drools、SpEL 等主流方案这套零依赖表达式引擎具备极强的生产落地优势轻量化、高安全、易接入完美适配中小型项目轻量化开发零重型依赖仅依赖FastJSON、Slf4j基础工具无第三方重型框架依赖项目零侵入、无冗余绝对安全摒弃SpEL脚本编译执行模式无脚本注入漏洞彻底规避安全风险生产环境更稳妥轻量高效基于栈逆波兰算法自研解析逻辑执行性能远超传统脚本引擎轻量化无性能损耗高可拓展预留拓展接口支持自定义新增运算符可根据个性化业务自由迭代生产稳定全场景容错适配兼容各类异常数据场景稳定性适配线上生产环境三、基础版实现兼容通用场景基础版核心代码实现Java零依赖动态条件解析核心能力满足绝大多数常规动态规则场景代码注释精简统一、逻辑清晰可直接复制复用至项目开发高效替代传统ifelse臃肿硬编码逻辑。/** * 轻量级自定义条件表达式解析工具【生产稳定基础版】 * 核心能力多层括号嵌套、数值运算、字符串匹配、逻辑与或、JSON动态字段解析 * 核心优势零脚本注入风险、轻量无依赖、高容错、可配置、零侵入接入 * 业务场景动态规则过滤、用户画像圈选、日志告警、流程分支、动态权限校验 * 优化点修复优先级BUG、空指针防护、全局异常容错、规范日志输出 * * version 1.0.1 生产优化版 * author yzjyhp */ package com.qizhidao.tags.utils; import com.alibaba.fastjson.JSONPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ParserUtil { protected static Logger logger LoggerFactory.getLogger(ParserUtil.class); /** * 运算符优先级映射数值越小优先级越高 */ private static MapString, Integer operatorMap null; /** * 静态初始化运算符优先级规则 */ static { operatorMap new HashMap(); operatorMap.put((, 1); operatorMap.put(), 1); operatorMap.put(and, 11); operatorMap.put(or, 12); operatorMap.put(, 7); operatorMap.put(!, 7); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(contains, 14); operatorMap.put(containsnot, 14); } /** * 运算符枚举统一管理标准化内置运算符与匹配逻辑 */ enum Op { // 数值比较运算符 GT(), GE(), LT(), LE(), // 等值匹配运算符 EQ(), NOT_EQ(!), // 逻辑运算运算符 AND(and), OR(or), // 字符串匹配运算符 CONTAINS(contains), CONTAINS_NOT(containsnot); private String operator; Op(String operator) { this.operator operator; } public String getOperator() { return operator; } /** * 根据运算符字符串匹配对应枚举 * param operator 运算符字符串 * return 对应枚举对象 */ public static Op getByOperator(String operator) { if (operator null || operator.length() 0) { return null; } for (Op op : Op.values()) { if (op.getOperator().equalsIgnoreCase(operator)) { return op; } } return null; } } /** * 表达式分词剔除无效空格生成标准化Token语法单元 * param pattern 原始表达式字符串 * return 标准化Token集合 */ private static ArrayListString getTokens(String pattern) { String[] splitArr pattern.split( ); ArrayListString tokens new ArrayList(); for (String split : splitArr) { String trim split.trim(); if (!trim.isEmpty()) { tokens.add(trim); } } return tokens; } /** * 对外统一解析入口支持多层括号嵌套全局异常容错 * param pattern 自定义规则表达式 * param log 业务JSON上下文数据 * return 规则匹配结果 true/false */ public static boolean calculate(String pattern, String log) { try { // 递归消解所有括号嵌套扁平化表达式 if (pattern.contains(()) { pattern calculate1(pattern, log); } // 执行平铺表达式核心解析计算 return calculateExt(pattern, log); } catch (Exception e) { logger.warn(【表达式解析异常】pattern:{},log:{},msg:{}, pattern, log, e.getMessage()); logger.error(【表达式异常堆栈信息】, e); } return false; } /** * 递归消解括号嵌套逐层解析内层表达式并扁平化处理 * param pattern 嵌套表达式 * param log 业务JSON上下文数据 * return 扁平化后的纯逻辑表达式 * throws Exception 语法格式异常 */ private static String calculate1(String pattern, String log) throws Exception { String regex \\([^()]\\); Pattern pa Pattern.compile(regex); Matcher m pa.matcher(pattern); String pattern2 pattern; // 循环匹配并消解最内层括号 while (m.find()) { String subExpr m.group(); boolean subResult calculateExt(subExpr, log); pattern2 pattern2.replace(subExpr, subResult ? true : false); } // 递归处理剩余嵌套括号 if (pattern2.contains(()) { pattern2 calculate1(pattern2, log); } return pattern2; } /** * 平铺表达式核心求值方法基于逆波兰算法栈结构精准解析 * param pattern 扁平化表达式 * param log 业务JSON上下文数据 * return 匹配结果 true/false * throws Exception 解析异常 */ public static boolean calculateExt(String pattern, String log) throws Exception { StackString stack new Stack(); ArrayListString tokens generateReversePolish(getTokens(pattern)); // 遍历后缀表达式栈结构求值 for (String token : tokens) { if (!operatorMap.containsKey(token.toLowerCase())) { stack.push(token); } else { String right getValueFromContext(stack.pop(), log); String left getValueFromContext(stack.pop(), log); stack.push(operate(left, right, token).toString()); } } return stack.size() 1 true.equalsIgnoreCase(stack.pop()); } /** * 上下文数据取值工具支持常量、JSONPath字段动态取值 * param variable 表达式变量/常量 * param log 业务JSON上下文数据 * return 变量对应实际值 */ private static String getValueFromContext(String variable, String log) { // 普通常量直接返回 if (!variable.contains($)) { return variable; } // 全局日志占位符 if ($.equalsIgnoreCase(variable)) { return log; } // JSONPath字段取值 if (variable.contains($.)) { return String.valueOf(JSONPath.read(log, variable)); } return null; } /** * 中缀表达式转逆波兰后缀表达式解决运算符优先级混乱问题 * param tokens 标准化Token列表 * return 逆波兰后缀表达式Token列表 * throws Exception 括号不匹配等语法异常 */ private static ArrayListString generateReversePolish(ArrayListString tokens) throws Exception { StackString operatorStack new Stack(); StackString numberStack new Stack(); for (String token : tokens) { String lowerToken token.toLowerCase(); // 非运算符直接入数值栈 if (!operatorMap.containsKey(lowerToken)) { numberStack.push(token); } else { // 运算符栈为空直接入栈 if (operatorStack.empty()) { operatorStack.push(lowerToken); } else { // 遇到右括号弹出栈内运算符直至匹配左括号 if ().equals(token)) { String popToken; try { while (!(.equals(popToken operatorStack.pop())) { numberStack.push(popToken); } continue; } catch (EmptyStackException e) { throw new Exception(表达式括号不匹配语法非法, e); } } String preOperator operatorStack.peek(); // 左括号直接入栈 if ((.equals(preOperator)) { operatorStack.push(lowerToken); } // 当前运算符优先级更高栈顶运算符出栈 else if (operatorMap.get(lowerToken) operatorMap.get(preOperator)) { numberStack.push(operatorStack.pop()); operatorStack.push(lowerToken); } // 优先级更低或相等直接入栈 else { operatorStack.push(lowerToken); } } } } // 遍历结束弹出剩余所有运算符 while (!operatorStack.empty()) { numberStack.push(operatorStack.pop()); } return new ArrayList(Arrays.asList(numberStack.toArray(new String[0]))); } /** * 核心运算逻辑分发统一处理数值、字符串、逻辑运算 * param left 左运算值 * param right 右运算值 * param op 运算符 * return 运算结果 true/false */ private static Boolean operate(String left, String right, String op) { Op operator Op.getByOperator(op); if (operator null) { logger.warn(【未知运算符】op {}, op); return false; } Double leftNum, rightNum; switch (operator) { // 数值大小比较 case GT: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case GE: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case LT: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case LE: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; // 等值判断 case EQ: return Objects.equals(left, right); case NOT_EQ: return !Objects.equals(left, right); // 逻辑与或 case AND: return true.equals(left) true.equals(right); case OR: return true.equals(left) || true.equals(right); // 字符串包含匹配 case CONTAINS: return left ! null right ! null left.contains(right); case CONTAINS_NOT: return left ! null right ! null !left.contains(right); default: return false; } } /** * 全场景测试入口覆盖常规及异常业务场景 */ public static void main(String[] args) { String normalLog {\name\:\zhangsan\,\age\:12,\tex\:12,\email\:\zhangsan163.com\}; String emptyLog {}; String errorLog name:zhangsan,age:12; boolean test1 ParserUtil.calculate(( $.name zhangsan ) and ( ( ( $.age 10 ) and ( $.tex 10 ) ) and ( $.age 13 ) ), normalLog); System.out.println(用例1【多层嵌套全命中】预期true实际结果 test1); boolean test2 ParserUtil.calculate(( $.name zhangsan ) and ( $.age 15 ), normalLog); System.out.println(用例2【AND条件未命中】预期false实际结果 test2); boolean test3 ParserUtil.calculate($.age 15 or $.tex 12, normalLog); System.out.println(用例3【OR单条件命中】预期true实际结果 test3); boolean test4 ParserUtil.calculate($.email contains 163.com, normalLog); System.out.println(用例4【字符串包含匹配】预期true实际结果 test4); boolean test5 ParserUtil.calculate($.name containsnot lisi, normalLog); System.out.println(用例5【字符串不包含匹配】预期true实际结果 test5); boolean test6 ParserUtil.calculate($.age ! 15, normalLog); System.out.println(用例6【数值不等判断】预期true实际结果 test6); boolean test7 ParserUtil.calculate(( $.age 10 and $.age 15 ) or ( $.tex 20 ), normalLog); System.out.println(用例7【混合嵌套规则】预期true实际结果 test7); boolean test8 ParserUtil.calculate($.age 12 and $.age 12, normalLog); System.out.println(用例8【边界值匹配】预期true实际结果 test8); boolean test9 ParserUtil.calculate($.name zhangsan, emptyLog); System.out.println(用例9【空数据容错】预期false实际结果 test9); boolean test10 ParserUtil.calculate($.age 10 and , normalLog); System.out.println(用例10【非法表达式容错】预期false实际结果 test10); boolean test11 ParserUtil.calculate($.name contains zhangsan, errorLog); System.out.println(用例11【非法JSON容错】预期false实际结果 test11); } }四、高阶增强版实现数组解析语法校验在基础解析能力之上重磅拓展JSON数组解析、自定义运算符、表达式语法预校验等高阶能力打造完整版轻量级Java规则引擎适配复杂业务场景生产兼容性、稳定性更强彻底满足企业级动态规则开发需求。/** * 轻量级自定义条件表达式解析工具【增强扩展版】 * 原生能力多层括号嵌套、数值运算、字符串匹配、逻辑与或、JSON取值 * 高阶扩展自定义运算符、JSON数组解析、表达式语法预校验 * 核心优势向下兼容、零脚本风险、高拓展容错、轻量开箱即用 * 业务场景动态规则匹配、用户画像、风控告警、前端表达式配置校验 * * version 1.1.0 高阶扩展版 * author yzjyhp */ package com.qizhidao.tags.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ParserUtil { protected static Logger logger LoggerFactory.getLogger(ParserUtil.class); /** * 基础运算符优先级映射数值越小优先级越高 */ private static MapString, Integer operatorMap null; /** * 自定义扩展运算符集合支持业务灵活拓展 */ private static final SetString CUSTOM_OP_SET; /** * 初始化基础运算符与自定义扩展运算符 */ static { // 初始化原生基础运算符 operatorMap new HashMap(); operatorMap.put((, 1); operatorMap.put(), 1); operatorMap.put(and, 11); operatorMap.put(or, 12); operatorMap.put(, 7); operatorMap.put(!, 7); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(, 6); operatorMap.put(contains, 14); operatorMap.put(containsnot, 14); // 初始化自定义高阶运算符 CUSTOM_OP_SET new HashSet(); CUSTOM_OP_SET.add(arrayContain); CUSTOM_OP_SET.add(arrayNotContain); CUSTOM_OP_SET.add(arrayLenEq); CUSTOM_OP_SET.add(arrayLenGt); CUSTOM_OP_SET.add(notNull); CUSTOM_OP_SET.add(like); } /** * 全量运算符枚举原生自定义统一运算分发逻辑 */ enum Op { // 原生基础运算符 GT(), GE(), LT(), LE(), EQ(), NOT_EQ(!), AND(and), OR(or), CONTAINS(contains), CONTAINS_NOT(containsnot), // 自定义扩展运算符 ARRAY_CONTAIN(arrayContain), ARRAY_NOT_CONTAIN(arrayNotContain), ARRAY_LEN_EQ(arrayLenEq), ARRAY_LEN_GT(arrayLenGt), NOT_NULL(notNull), LIKE(like); private String operator; Op(String operator) { this.operator operator; } public String getOperator() { return operator; } /** * 全局匹配运算符枚举 * param operator 运算符字符串 * return 对应枚举对象 */ public static Op getByOperator(String operator) { if (operator null || operator.length() 0) { return null; } for (Op op : Op.values()) { if (op.getOperator().equalsIgnoreCase(operator)) { return op; } } return null; } } /** * 表达式分词生成标准化Token单元 * param pattern 原始表达式字符串 * return 标准化Token集合 */ private static ArrayListString getTokens(String pattern) { String[] splitArr pattern.split( ); ArrayListString tokens new ArrayList(); for (String split : splitArr) { String trim split.trim(); if (!trim.isEmpty()) { tokens.add(trim); } } return tokens; } // 原生核心解析方法完全向下兼容 /** * 对外统一解析入口兼容旧版所有表达式语法 * param pattern 自定义规则表达式 * param log 业务JSON上下文数据 * return 规则匹配结果 true/false */ public static boolean calculate(String pattern, String log) { try { if (pattern.contains(()) { pattern calculate1(pattern, log); } return calculateExt(pattern, log); } catch (Exception e) { logger.warn(【表达式解析异常】pattern:{},log:{},msg:{}, pattern, log, e.getMessage()); logger.error(【表达式异常堆栈】, e); } return false; } /** * 递归消解括号嵌套扁平化复杂表达式 * param pattern 嵌套表达式 * param log 业务JSON上下文数据 * return 扁平化表达式 * throws Exception 语法异常 */ private static String calculate1(String pattern, String log) throws Exception { String regex \\([^()]\\); Pattern pa Pattern.compile(regex); Matcher m pa.matcher(pattern); String pattern2 pattern; while (m.find()) { String subExpr m.group(); boolean subResult calculateExt(subExpr, log); pattern2 pattern2.replace(subExpr, subResult ? true : false); } if (pattern2.contains(()) { pattern2 calculate1(pattern2, log); } return pattern2; } /** * 平铺表达式核心求值兼容原生自定义运算符 * param pattern 扁平化表达式 * param log 业务JSON上下文数据 * return 匹配结果 true/false * throws Exception 解析异常 */ public static boolean calculateExt(String pattern, String log) throws Exception { StackString stack new Stack(); ArrayListString tokens generateReversePolish(getTokens(pattern)); for (String token : tokens) { String lowerToken token.toLowerCase(); if (!operatorMap.containsKey(lowerToken) !CUSTOM_OP_SET.contains(lowerToken)) { stack.push(token); } else { String right getValueFromContext(stack.pop(), log); String left getValueFromContext(stack.pop(), log); stack.push(operate(left, right, token).toString()); } } return stack.size() 1 true.equalsIgnoreCase(stack.pop()); } /** * 上下文动态取值兼容常量、普通字段、JSON数组字段 * param variable 表达式变量/常量 * param log 业务JSON上下文数据 * return 变量实际取值 */ private static String getValueFromContext(String variable, String log) { if (!variable.contains($)) { return variable; } if ($.equalsIgnoreCase(variable)) { return log; } if (variable.contains($.)) { return String.valueOf(JSONPath.read(log, variable)); } return null; } /** * 中缀转逆波兰后缀表达式统一运算优先级 * param tokens 标准化Token列表 * return 逆波兰后缀表达式Token列表 * throws Exception 语法异常 */ private static ArrayListString generateReversePolish(ArrayListString tokens) throws Exception { StackString operatorStack new Stack(); StackString numberStack new Stack(); for (String token : tokens) { String lowerToken token.toLowerCase(); if (!operatorMap.containsKey(lowerToken) !CUSTOM_OP_SET.contains(lowerToken)) { numberStack.push(token); } else { if (operatorStack.empty()) { operatorStack.push(lowerToken); } else { if ().equals(token)) { String popToken; try { while (!(.equals(popToken operatorStack.pop())) { numberStack.push(popToken); } continue; } catch (EmptyStackException e) { throw new Exception(表达式括号不匹配语法非法, e); } } String preOperator operatorStack.peek(); if ((.equals(preOperator)) { operatorStack.push(lowerToken); } else if (operatorMap.containsKey(lowerToken) operatorMap.get(lowerToken) operatorMap.get(preOperator)) { numberStack.push(operatorStack.pop()); operatorStack.push(lowerToken); } else { operatorStack.push(lowerToken); } } } } while (!operatorStack.empty()) { numberStack.push(operatorStack.pop()); } return new ArrayList(Arrays.asList(numberStack.toArray(new String[0]))); } // 高阶扩展运算逻辑自定义运算符数组解析 /** * 全局运算逻辑分发兼容原生及高阶自定义运算 * param left 左运算值 * param right 右运算值 * param op 运算符 * return 运算结果 true/false */ private static Boolean operate(String left, String right, String op) { Op operator Op.getByOperator(op); if (operator null) { logger.warn(【未知运算符】op {}, op); return false; } Double leftNum, rightNum; switch (operator) { // 基础数值运算 case GT: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case GE: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case LT: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; case LE: leftNum Double.valueOf(left); rightNum Double.valueOf(right); return leftNum rightNum; // 基础等值运算 case EQ: return Objects.equals(left, right); case NOT_EQ: return !Objects.equals(left, right); // 基础逻辑运算 case AND: return true.equals(left) true.equals(right); case OR: return true.equals(left) || true.equals(right); // 基础字符串运算 case CONTAINS: return left ! null right ! null left.contains(right); case CONTAINS_NOT: return left ! null right ! null !left.contains(right); // 自定义数组运算 case ARRAY_CONTAIN: return arrayContain(left, right); case ARRAY_NOT_CONTAIN: return !arrayContain(left, right); case ARRAY_LEN_EQ: return arrayLengthEqual(left, right); case ARRAY_LEN_GT: return arrayLengthGt(left, right); // 自定义通用运算 case NOT_NULL: return left ! null !.equals(left) !null.equalsIgnoreCase(left); case LIKE: return left ! null right ! null left.matches(.* right .*); default: return false; } } // 数组解析工具方法 /** * JSON数组元素包含判断兼容字符串/数值数组自带容错 * param arrayStr JSON数组字符串 * param target 待匹配元素 * return 包含返回true否则false */ private static boolean arrayContain(String arrayStr, String target) { if (arrayStr null || target null) { return false; } try { JSONArray jsonArray JSON.parseArray(arrayStr); return jsonArray.contains(target) || jsonArray.contains(Integer.parseInt(target)) || jsonArray.contains(Double.parseDouble(target)); } catch (Exception e) { logger.warn(【数组匹配异常】array:{},target:{}, arrayStr, target); return false; } } /** * JSON数组长度精准匹配 * param arrayStr JSON数组字符串 * param len 目标长度 * return 长度一致返回true */ private static boolean arrayLengthEqual(String arrayStr, String len) { if (arrayStr null || len null) { return false; } try { JSONArray jsonArray JSON.parseArray(arrayStr); return jsonArray.size() Integer.parseInt(len); } catch (Exception e) { logger.warn(【数组长度判断异常】array:{},len:{}, arrayStr, len); return false; } } /** * JSON数组长度大于判断 * param arrayStr JSON数组字符串 * param len 对比长度 * return 数组长度更大返回true */ private static boolean arrayLengthGt(String arrayStr, String len) { if (arrayStr null || len null) { return false; } try { JSONArray jsonArray JSON.parseArray(arrayStr); return jsonArray.size() Integer.parseInt(len); } catch (Exception e) { logger.warn(【数组长度判断异常】array:{},len:{}, arrayStr, len); return false; } } // 表达式预校验工具 /** * 表达式语法全局预校验前置拦截非法表达式 * param pattern 待校验自定义表达式 * return 校验结果状态提示信息 */ public static ExprValidateResult validateExpr(String pattern) { // 空表达式校验 if (pattern null || pattern.trim().isEmpty()) { return new ExprValidateResult(false, 表达式不能为空); } // 括号完整性校验 if (!checkBracketMatch(pattern)) { return new ExprValidateResult(false, 表达式括号不匹配语法非法); } // 运算符合法性校验 ListString tokenList getTokens(pattern); for (String token : tokenList) { String lowerToken token.toLowerCase(); if (operatorMap.containsKey(lowerToken) || CUSTOM_OP_SET.contains(lowerToken)) { continue; } if (lowerToken.startsWith($) || isNumber(lowerToken) || isNormalStr(lowerToken)) { continue; } return new ExprValidateResult(false, 存在未知非法运算符/字符 token); } // 整体语法格式校验 if (!checkExprFormat(tokenList)) { return new ExprValidateResult(false, 表达式语法格式错误运算符位置非法); } return new ExprValidateResult(true, 表达式语法合法); } /** * 校验多层括号是否完整闭合 * param pattern 表达式字符串 * return 闭合返回true */ private static boolean checkBracketMatch(String pattern) { StackCharacter stack new Stack(); for (char c : pattern.toCharArray()) { if (( c) { stack.push(c); } else if () c) { if (stack.isEmpty()) { return false; } stack.pop(); } } return stack.isEmpty(); } /** * 校验字符串是否为纯数字 * param str 待校验字符串 * return 纯数字返回true */ private static boolean isNumber(String str) { try { Double.parseDouble(str); return true; } catch (Exception e) { return false; } } /** * 校验是否为合法普通字符串排除语法关键字 * param str 待校验字符串 * return 合法返回true */ private static boolean isNormalStr(String str) { return !str.contains(() !str.contains()) !str.contains(and) !str.contains(or); } /** * 校验表达式整体格式拦截非法运算符位置 * param tokens 标准化Token列表 * return 格式合法返回true */ private static boolean checkExprFormat(ListString tokens) { ListString allOp new ArrayList(operatorMap.keySet()); allOp.addAll(CUSTOM_OP_SET); // 首尾禁止为运算符 String first tokens.get(0).toLowerCase(); String last tokens.get(tokens.size() - 1).toLowerCase(); if (allOp.contains(first) !(.equals(first)) { return false; } if (allOp.contains(last) !).equals(last)) { return false; } // 禁止连续运算符 for (int i 1; i tokens.size(); i) { String curr tokens.get(i).toLowerCase(); String prev tokens.get(i - 1).toLowerCase(); if (allOp.contains(curr) allOp.contains(prev) !(.equals(curr) !).equals(prev)) { return false; } } return true; } /** * 表达式校验结果实体结构化返回校验信息 */ public static class ExprValidateResult { private boolean success; private String msg; public ExprValidateResult(boolean success, String msg) { this.success success; this.msg msg; } public boolean isSuccess() { return success; } public String getMsg() { return msg; } } // 高阶能力测试用例 /** * 高阶扩展能力测试入口覆盖数组解析、自定义运算符、表达式预校验 */ public static void main(String[] args) { // 含数组结构的业务测试数据 String arrayLog {\name\:\zhangsan\,\age\:18,\tags\:[\java\,\spring\,\mysql\],\score\:[90,88,95]}; // 普通业务测试数据 String normalLog {\name\:\zhangsan\,\age\:12,\tex\:12,\email\:\zhangsan163.com\}; // 1. 表达式预校验测试 ExprValidateResult valid1 validateExpr($.tags arrayContain java); System.out.println(预校验合法表达式 valid1.isSuccess() 信息 valid1.getMsg()); ExprValidateResult valid2 validateExpr($.age 10 and ); System.out.println(预校验非法表达式 valid2.isSuccess() 信息 valid2.getMsg()); // 2. 数组包含元素匹配测试 boolean testArr1 calculate($.tags arrayContain java, arrayLog); System.out.println(数组包含元素【预期true】 testArr1); // 3. 数组长度精准匹配测试 boolean testArr2 calculate($.tags arrayLenEq 3, arrayLog); System.out.println(数组长度等于3【预期true】 testArr2); // 4. 自定义模糊匹配测试 boolean testLike calculate($.email like 163, normalLog); System.out.println(模糊匹配163【预期true】 testLike); // 5. 字段非空校验测试 boolean testNotNull calculate($.name notNull , normalLog); System.out.println(name非空校验【预期true】 testNotNull); } }五、高阶能力业务实战示例下面演示JSON数组条件匹配、模糊查询、表达式前置校验等高阶能力的生产级写法贴合真实业务场景可直接复用至企业级业务代码快速实现业务动态规则配置化开发。// 含数组结构的真实业务JSON数据 String bizLog {\userTags\:[\vip\,\newUser\,\active\],\scoreList\:[85,92,78],\phone\:\13812345678\}; // 1. 数组规则组合匹配标签包含vip 且 标签数组长度大于2 boolean res1 ParserUtil.calculate($.userTags arrayContain vip and $.userTags arrayLenGt 2, bizLog); // 2. 自定义模糊匹配手机号包含138前缀 boolean res2 ParserUtil.calculate($.phone like 138, bizLog); // 3. 字段非空合法性校验 boolean res3 ParserUtil.calculate($.phone notNull , bizLog); // 4. 表达式前置预校验合法后再执行解析生产推荐写法 ParserUtil.ExprValidateResult result ParserUtil.validateExpr($.scoreList arrayLenEq 3); if(result.isSuccess()){ boolean res4 ParserUtil.calculate($.scoreList arrayLenEq 3, bizLog); }写在最后相比于 Drools、SpEL 等重型、高风险的规则方案这套自研零依赖Java表达式解析引擎最大的优势就是零依赖、高安全、低成本、可落地。无需引入复杂框架、无需繁琐配置就能完美替代臃肿的 if/else 硬编码逻辑实现业务规则完全配置化、动态化彻底解决改规则必改代码、频繁发版的开发痛点。本文提供的基础版高阶增强版两套源码覆盖了从常规条件判断、复杂嵌套规则到JSON数组解析、语法预校验的全场景能力代码注释规范、容错完善可直接复制落地到生产项目适配风控校验、用户画像、日志筛选、流程分支等绝大多数动态规则开发场景。后续我会持续更新该引擎的拓展功能比如新增更多业务运算符、支持变量默认值、适配前端可视化表达式配置等进阶能力。持续分享Java生产实战技巧、自研工具源码、避坑干货与架构实践帮你简化业务开发、提升编码效率觉得本文实用欢迎点赞、收藏、转发关注我持续解锁更多优质技术内容