在Spel中,可以很容易地为List属性分配一些值。 例如,如果对象foo的属性定义为List,我通常会这样做:
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分配值的情况,您如何处理? 定义为方法中的变量。 e.g:
List<String> fooList = new ArrayList<String>();
context = new StandardEvaluationContext(fooList);
parser.parseExpression("SOMETHING[0]='come on'")
.getValue(context);
在上面的例子中,我不知道要放什么而不是SOMETHING来使这项工作。 如果我输入“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,但我注意到它们不支持自动空引用初始化,这对我很重要。然而,他们似乎也无法解决上述问题。
我也开始思考如果我需要的不是表达语言的情况! 问题是我的需要不仅仅是定义变量并尝试使用EL分配值。
在我的例子中,我有一些简单的POJO域类bean和一些输入字符串,如
"bar[0].foo.value=3434"
现在我应该能够创建Bar of Bar并将Bar实例作为其第一个元素,然后使用Foo实例设置foo属性,最后将Foo的值设置为3434.
关于这个问题的任何想法?
提前致谢
EIT 我错了“然而他们似乎也无法解决上述问题”。例如在MVEL中,这是一项非常容易的任务。但不幸的是,SPLE能够自动扩展列表并自动在空链中分配启动器,这使得它非常适合我的情况。
答案 0 :(得分:1)
您必须在表达式中定义一个变量,并将其填入要处理的列表中,例如
context.setVariable("mylist", fooList);
然后你可以像这样访问它:
parser.parseExpression("#mylist.set(0)='come on'").getValue(context);
变量中的列表由反射使用;你可以打电话等方法 我希望这会有所帮助。
答案 1 :(得分:0)
问题是由于Java中的类型擦除,Spring或其他Els没有线索在包含列表的通用根对象的链中自动启动空值。 例如,在SpEl:
中的表达式中#root[10].mySet='ohoy'
如果它检测到它需要首先启动ArrayList,则无法知道在给定索引处启动的正确元素Type是什么。 这就是为什么它需要一个包装来使用getter的返回类型的反映。
另一项工作是使用数组。因为数组组件类型保留在运行时。但问题是数组无法在运行时调整大小。 因此,它们需要以足够大的尺寸启动,以防止索引超出范围。
无论如何,为了做这些事情,类型擦除也是一个真正的痛苦,似乎他们(也适用于其他EL)仍然可以做一些努力围绕这个做一些工作。例如
1)如果列表不为空,则可以在运行时从中获取真实元素的类型。
2)更改getValue以获取泛型类型传递参数并将其用于启动
3)对于数组,返回展开的数组
4)......
虽然实现一个承诺处理所有启动或扩展的良好EL似乎是一项非常艰苦的工作,但我正在努力扩展Ognl以实现这一点。我从
开始PropertyAccessor
并得到了一些非常有希望的结果。但是,在开发库时,我不知道apache有什么问题。例如,我不喜欢他们将处理程序放在Static类中的方式。我认为处理程序是一个上下文问题,但我不知道是否值得花费一些时间来扩展Ognl,但是一旦完成工作,我就会分享结果。
答案 2 :(得分:0)
根据this answer,以下方法应该起作用:
parser.parseExpression("obj").getValue(context, "olaaa"); // or is it "'olaaa'"?
甚至类似
parser.parseExpression("obj").getValue(context, "'olaaa', 'alooo'");
答案 3 :(得分:0)
就我而言,它是用户定义对象的数组列表。
上述解决方案均无效。
所以我一直在读到 arrayList 本身而不是对象的确切路径,一旦获取,我正在迭代和检查:-(
表达式 parsedValueExpression3 = parser.parseExpression("arraylist.root");
欢迎提出更好的建议。