【问题标题】:SpEL parsing parameters with "Collectors.toList()" in stream won't work as expressionString?流中带有“Collectors.toList()”的SpEL解析参数不能作为表达式字符串工作?
【发布时间】:2020-11-08 13:22:51
【问题描述】:

这会起作用

parser.parseExpression("#configList.stream().toArray()").getValue(context)

但以下不会

parser.parseExpression("#configList.stream().map(o -> o.ruleId).collect(Collectors.toList())").getValue(context)

F.Y.I 上下文构造如下:

        Object[] args = joinPoint.getArgs();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        String[] params = discoverer.getParameterNames(method);
        EvaluationContext context = new StandardEvaluationContext();
        for (int i = 0; i < params.length; i++) {
            context.setVariable(params[i], args[i]);
        }

【问题讨论】:

    标签: spring java-8 spring-el


    【解决方案1】:

    虽然 Java 可以在 SPeL 表达式中使用,但 SPeL 本身是一种单独的语言,并不完全支持 Java 语言。来自documentation

    SpEL 基于技术无关 API,允许在需要时集成其他表达式语言实现。

    要对 SPeL 表达式中的列表执行过滤和映射操作,请分别使用 collection selectioncollection projection

    集合选择示例

    // Java:
    configList.stream().filter(o -> o.getRuleId() > 2).collect(Collectors.toList())
    
    // SPeL (notice the question mark) :
    "#configList.?[ruleId>2]"
    

    集合投影示例

    // Java:
    configList.stream().map(o -> o.getRuleId()).collect(Collectors.toList())
    
    // SPeL (notice the exclamation mark) :
    "#configList.![ruleId]"
    
    

    我已经设置了一个小例子来演示它:

    public class So64738543ExpressionTest {
        public static class RuleItem {
            private int ruleId;
    
            public RuleItem(int ruleId) {
                this.ruleId = ruleId;
            }
    
            public int getRuleId() {
                return ruleId;
            }
        }
    
        @Test
        public void collectionProjection() {
            List<RuleItem> ruleItems = Arrays.asList(new RuleItem(1), new RuleItem(2), new RuleItem(3));
            EvaluationContext context = new StandardEvaluationContext(ruleItems);
    
            Expression expression = new SpelExpressionParser().parseExpression("#root.![ruleId]");
            Assert.assertEquals(Arrays.asList(1,2,3), expression.getValue(context));
        }
    }
    

    [编辑]

    此外,如果 SPeL 表达式变得越来越复杂,我强烈建议将表达式移动到静态方法并使用 T operator 调用它。引用静态方法时不要忘记包含完全限定的包名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多