Spring SpEL结合Stream API求和遇解析错误,求正确实现方案
问题解决思路与可行实现
核心问题分析
- SpEL不支持Java方法引用语法:你使用的
Integer::sum属于Java方法引用,SpEL解析器无法识别,这是触发EL1043E: Unexpected token报错的直接原因。 - split参数未转义:
|是正则表达式的元字符,直接调用split('|')会把字符串拆分为单个字符(比如"1|1|1|1"会被拆成["1","|","1","|","1","|","1"]),必须进行转义处理。 - 缺少类型转换:split返回的是String类型的流,直接执行求和操作会出现类型不匹配,需要先将元素转换为Integer类型。
可行实现方案
方案一:用SpEL支持的Lambda替代方法引用
修改SpEL表达式,替换方法引用为Lambda,同时处理split转义和类型转换:
T(java.util.Arrays).stream(value.split('\\|')).map(s -> T(Integer).valueOf(s)).reduce(0, (a,b) -> a+b)
对应的测试代码调整:
@Test fun `test sum values`() { val cont = ScriptingContext.default(); val contextrecord: Map<String, String> = mapOf( "value" to "1|1|1|1" ) val context = cont.getEvalContext() context.setRootObject(contextrecord) // 使用修正后的表达式 val value = cont.parser.parseExpression("T(java.util.Arrays).stream(value.split('\\\\|')).map(s -> T(Integer).valueOf(s)).reduce(0, (a,b) -> a+b)").getValue(context) as Int println(value) assertEquals(value, 4) }
方案二:用collect直接求和(更直观)
也可以借助Collectors.summingInt完成求和,同样需要处理转义和类型转换:
T(java.util.Arrays).stream(value.split('\\|')).mapToInt(s -> T(Integer).parseInt(s)).collect(T(java.util.stream.Collectors).summingInt(i -> i))
关键细节说明
- split转义:在SpEL中,转义字符需要写两次
\\——第一次是字符串层面的转义,第二次是正则表达式层面的转义,因此'\\|'最终会被解析为正则的\|。 - 类型转换:通过
map(s -> T(Integer).valueOf(s))或mapToInt将String转换为Integer/int类型,确保求和操作的类型合法性。 - SpEL Lambda支持:SpEL 3.0及以上版本支持Lambda表达式,格式为
(参数) -> 表达式,可以完美替代Java方法引用完成聚合操作。
内容的提问来源于stack exchange,提问作者Anas Altarazi
相关产品推荐
相关产品推荐

