You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot3中Spel Expression Parser无法识别application.properties中的公式

问题解决:SpEL表达式从application.properties读取后解析失败

核心问题:表达式语法错误

你遇到的SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'comma(,)'错误,根源是application.properties中的SpEL表达式存在括号不匹配的语法问题:

  • Math.max的第一个参数外层多了一个多余的右括号),导致第一个参数提前闭合
  • 表达式末尾还多了一个多余的右括号)

这两个错误直接导致SpEL解析器认为逗号,是多余的无效内容,触发解析失败。

修正后的正确表达式

将application.properties中的formula.expression替换为以下正确语法的表达式:

formula.expression=T(java.lang.Math).max(1.0 / (T(java.time.temporal.ChronoUnit).DAYS.between(T(java.time.LocalDate).now(), loan.getDueDate().toLocalDate()) + 1), T(java.time.temporal.ChronoUnit).DAYS.between(loan.getDueDate().toLocalDate(), T(java.time.LocalDate).now()))

语法修正点说明:

  1. 移除了1.0 / (...) +1外层多余的右括号,确保Math.max的第一个参数是完整的1.0 / (天数差 +1)
  2. 移除了表达式末尾多余的右括号,保证整个表达式的括号完全匹配

额外优化建议

  1. 避免重复计算当前日期:
    在convertExpression方法中,将LocalDate.now()存入EvaluationContext变量,避免表达式中重复调用,同时保证计算时的日期一致性:

    private double convertExpression(String expression, Loan loan) {
        System.out.println("dueDate"+loan.getDueDate());
        try {
            System.out.println("exp"+expression);
            ExpressionParser parser = new SpelExpressionParser();
            StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
            evaluationContext.setVariable("loan", loan);
            // 添加当前日期变量
            evaluationContext.setVariable("currentDate", LocalDate.now());
            Expression exp = parser.parseExpression(expression);
            System.out.println(exp+"jhasbufwqfi");
            Double evaluatedValue = exp.getValue(evaluationContext, Double.class);
            System.out.println("evaluated"+evaluatedValue);
            return evaluatedValue;
        } catch (Exception e) {
            throw new IllegalArgumentException("Error evaluating expression: " + expression, e);
        }
    }
    

    对应的application.properties表达式可以简化为:

    formula.expression=T(java.lang.Math).max(1.0 / (T(java.time.temporal.ChronoUnit).DAYS.between(currentDate, loan.getDueDate().toLocalDate()) + 1), T(java.time.temporal.ChronoUnit).DAYS.between(loan.getDueDate().toLocalDate(), currentDate))
    
  2. 空值与异常防护:
    可以在表达式中添加空值判断,避免loan.getDueDate()为null时抛出异常,例如使用?:运算符:

    formula.expression=T(java.lang.Math).max(1.0 / (T(java.time.temporal.ChronoUnit).DAYS.between(currentDate, loan.getDueDate()?.toLocalDate() ?: currentDate) + 1), T(java.time.temporal.ChronoUnit).DAYS.between(loan.getDueDate()?.toLocalDate() ?: currentDate, currentDate))
    

    当loan.getDueDate()为null时,默认使用当前日期计算,避免空指针异常。

验证步骤

  1. 先在代码中硬编码修正后的表达式,调用convertExpression方法测试,确认能正确计算结果
  2. 将修正后的表达式写入application.properties,重启服务测试调度任务是否正常运行

内容的提问来源于stack exchange,提问作者Karthik KK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:45:02