是否在spring表达式(SpEL)中支持的投影集合对象的字段上设置值?

时间:2016-03-08 16:55:00

标签: java spring spring-el

弹簧表达式(SpEL)支持投影集合对象的设置值吗?

尝试运行示例代码时出现以下错误。

Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1068E:(pos 1310742): the expression component '![comment]' is not assignable

我要做的是 - 在符合特定条件的所有对象上设置一个值。 (下面的示例可能不符合最佳实践,因为我试图保持简单快速)

package com.test;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

public class SpELTest {

    public static class Person {
        public String name;
        public int age;
        public String comment;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", comment='" + comment + '\'' +
                '}';
        }
    }

    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Person 1", 10));
        people.add(new Person("Person 2", 20));
        people.add(new Person("Person 3", 30));
        people.add(new Person("Person 4", 40));
        people.add(new Person("Person 5", 50));
        people.add(new Person("Person 6", 60));
        people.add(new Person("Person 7", 70));
        people.add(new Person("Person 8", 80));

        ExpressionParser parser = new SpelExpressionParser();

        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("people", people);

        // check the projected
        List<String> projected = (List<String>) parser.parseExpression("#people.?[age > 50].![name]").getValue(context);
        for (String p : projected) {
            System.out.println(p);
        }

        // use expression to set values
        parser.parseExpression("#people.?[age > 50].![comment]").setValue(context, "older than 50");

        for (Person p : people) {
            System.out.println(p);
        }
    }

}

输出:

Person 6
Person 7
Person 8
Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1068E:(pos 1310742): the expression component '![comment]' is not assignable
    at org.springframework.expression.spel.ast.ValueRef$TypedValueHolderValueRef.setValue(ValueRef.java:78)
    at org.springframework.expression.spel.ast.CompoundExpression.setValue(CompoundExpression.java:87)
    at org.springframework.expression.spel.standard.SpelExpression.setValue(SpelExpression.java:169)
    at com.test.SpELTest.main(SpELTest.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    at java.lang.reflect.Method.invoke(Method.java:613)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

1 个答案:

答案 0 :(得分:0)

您的代码中存在两个问题。

首先 - 你无法对一些简单属性的投射进行分配。

让我们考虑以下课程:

class Person {
    String name
}

可以通过

更改Person的名称
person.name = "newValue"

但你要做的是:

String projection = person.name
projection = "newValue"

这不会奏效。

第二件事是您无法将值older than 50分配给集合(List)。 你可以做这样的事情:

parser.parseExpression("(#people.?[age > 50 and comment == null])[0].comment")
      .setValue(context, "older than 50");

但这只会改变结果投影中的第一项。

SpEL没有简单的方法可以执行此操作,但您可以通过context.registerFunction注册一些外部函数。这样的函数可以接受Person对象的收集并对它们执行变异。