如何使用 Spring 表达式语言(或您知道的其他表达式语言)为定义为变量的某些对象列表赋值

How to assign values for a list of some objects defined as variable with Spring Expression Language(Or the other expression languages you aware of)

在 Spel 中,很容易为列表分配一些值 属性。 例如,将带有 属性 的对象 foo 定义为列表,我通常会这样做:

SpelParserConfiguration config = new SpelParserConfiguration(true,true);
ExpressionParser parser = new SpelExpressionParser(config);
Foo foo = new Foo();
EvaluationContext context = new StandardEvaluationContext(foo);
parser.parseExpression("barList[1].test='11111111'")
    .getValue(context);

但是如果你想为给定的列表赋值,你会怎么做 定义为方法中的变量。例如:

List<String> fooList = new ArrayList<String>();
context = new StandardEvaluationContext(fooList);       
parser.parseExpression("SOMETHING[0]='come on'")
.getValue(context);

在上面的例子中,我不知道该用什么代替一些东西来完成这项工作。 如果我输入 "fooList[0]='....'",它会抛出一个异常,抱怨 fooList.

中没有 fooList 属性

如果我输入“[0]='....'”,它会抛出无法增加集合:无法确定列表元素类型。

然后我开始像这样定义一个通用包装器:

public static class SpelWrapper<T>
{
    T obj;

    public SpelWrapper(T obj)
    {
        this.obj = obj;
    }

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

然后尝试测试这个:

List<String> fooList = new ArrayList<String>();
    SpelWrapper<List<String>> no = new SpelWrapper<List<String>>(fooList);
    context = new StandardEvaluationContext(no);

    parser.parseExpression("obj[0]='olaaa'")
    .getValue(context);

但它没有用,仍然收到这条丑陋的消息:

Unable to grow collection: unable to determine list element type

我尝试了其他表达式语言,如 MVEL、OGNL、JEXL,但我注意到它们不支持对我来说很重要的自动空引用初始化。然而他们似乎也没有解决上述问题。

我也开始想如果我需要的不是表达式语言的case怎么办! 问题是我的需要不仅仅是定义一个变量并尝试使用 EL 赋值。

在我的例子中,我有一些简单的 POJO 域 class bean 和一些输入字符串,例如

 "bar[0].foo.value=3434"

现在我应该可以创建 Bar 列表并将 Bar 实例作为其第一个元素,然后使用 Foo 实例设置 foo 属性,最后将 Foo 的值设置为 3434。

对这个问题有什么想法吗?

提前致谢

Eit "However they did not seem to have a solution around above problem either" 我错了。例如在 MVEL 中,这是一项非常容易完成的任务。但不幸的是,SPLE 自动扩展列表和自动在空链中分配启动器的能力使其非常适合我的情况。

您必须在表达式中定义一个变量并用要处理的列表填充它,例如

context.setVariable("mylist", fooList);

然后你可以这样访问它:

parser.parseExpression("#mylist.set(0)='come on'").getValue(context);

变量中的列表被反射使用;你可以调用方法等。 希望对您有所帮助。

问题是由于 Java 中的类型擦除,Spring 或其他 Els 不知道如何在包括列表在内的通用根对象的链中自动启动空值。 例如,在 SpEl 中这样的表达式中:

#root[10].mySet='ohoy'

如果它检测到需要首先启动 ArrayList,则无法知道在给定索引处启动的正确元素类型是什么。 这就是为什么它需要一个包装器来使用 getter 的 return 类型的反射。

另一项工作是使用数组。因为数组组件类型保存在运行时。但要注意的是数组不能在运行时调整大小。 因此,它们需要以足够大的大小启动,以防止索引超出范围。

无论如何,为了做这些事情,类型擦除也是一个真正的痛苦,似乎他们(也应用其他 EL)仍然可以做一些努力来解决这个问题。例如

1) 如果列表不为空,则可以在运行时从中获取真实元素的类型。
2) 更改 getValue 以获取泛型传递参数并将其用于启动。
3) 对于数组,return 扩展数组。
4) ...

虽然实现一个承诺处理所有类型启动或扩展的良好 EL 似乎是一项非常艰巨的工作,但我正在努力扩展 Ognl 以实现这一点。我从

开始
PropertyAccessor

并得到了一些非常有希望的结果。但是,我不知道 apache 在开发库方面有什么问题。例如,我不喜欢他们将处理程序放在静态 class 中的方式。我认为处理程序是一个上下文问题,但我不知道是否值得花一些时间来扩展 Ognl,但是一旦我完成工作,我就会分享结果。

根据,以下应该有效:

parser.parseExpression("obj").getValue(context, "olaaa"); // or is it "'olaaa'"?

甚至类似

parser.parseExpression("obj").getValue(context, "'olaaa', 'alooo'");

在我的例子中,它是一个用户定义对象的数组列表。

None 上述解决方案有效。

所以我一直读到 arrayList 本身而不是对象的确切路径,一旦获取我就会迭代并检查:-(

表达式 parsedValueExpression3 = parser.parseExpression("arraylist.root");

如有更好的建议,我们将不胜感激。