如何使用Spring Expression Language(或您知道的其他表达语言)为某些定义为变量的对象的列表分配值 [英] 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)

查看:276
本文介绍了如何使用Spring Expression Language(或您知道的其他表达语言)为某些定义为变量的对象的列表分配值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  SpelParserConfiguration config = new SpelParserConfiguration( true,true); 
ExpressionParser解析器= 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] =‘来吧’)
.getValue(context);

在上面的示例中,我不知道要放些什么来完成这项工作。
如果我输入 fooList [0] ='....',则会抛出异常,提示fooList中没有fooList属性。



如果我放了[[0] ='....',它抛出了无法增长集合:无法确定列表元素类型。



然后我来定义一个通用包装器,例如:

 公共静态类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>>否=新的SpelWrapper< List< String>>(fooList);
context = new StandardEvaluationContext(否);

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

但是它没有用,仍然收到了这个难看的消息:

 无法增长集合:无法确定列表元素类型

我尝试了其他表达语言,例如MVEL,OGNL,JEXL,但我发现它们不支持自动空引用初始化,这对我很重要。但是,他们似乎也没有解决上述问题的方法。



我也开始考虑如果我需要的不是表达式语言的情况该怎么办!
我需要的不仅是定义变量并尝试使用EL赋值。



在我的情况下,我有一些简单的POJO域类bean和一些输入字符串,例如

  bar [0] .foo.value = 3434 

现在,我应该能够创建Bar列表并将Bar实例作为其第一个元素,然后将Foo属性设置为Foo实例,最后将Foo的值设置为3434。 b
$ b

开始
我错了尽管他们似乎也没有解决上述问题的方法。例如在MVEL中,这是一个非常容易完成的任务。但是不幸的是,SPLE能够自动扩展列表并自动在null链中分配启动器,这使得它非常适合我的情况。

解决方案

问题是由于Java,Spring或其他Els中的类型擦除没有自动启动null的线索包含根的通用根对象的链中。
例如,在SpEl中这样的表达式中:

  #root [10] .mySet ='ohoy'

如果检测到需要先启动ArrayList,则无法知道什么是适当的元素键入以给定索引启动。
这就是为什么需要包装器才能使用getter返回类型的反映。



另一种解决方法是使用数组。因为数组组件类型在运行时保留。但是要注意的是,数组无法在运行时调整大小。
因此,必须以足够大的大小来启动它们,以防止索引超出范围。



无论如何,Type擦除还是一个真正的痛苦。为了做这些事情,似乎它们(也适用于其他EL)仍然可以做出一些努力来使一些工作围绕此进行。例如



1)如果列表不为空,则可以在运行时从中获取实元素的类型。

2)更改getValue以获取传递的泛型类型并将其用于初始化。

3)对于数组,返回扩展数组。

4 )...



尽管实现一个承诺能够处理所有类型的引发或扩展的良好EL似乎是一项艰巨的工作,但我仍在努力扩展Ognl以实现这一目标问候。我从

  PropertyAccessor 


开始

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


In Spel, it is easy to assign some values for a List property. For example having object foo with a property defined as List, I usually do:

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);

But what do you do for the case you want to assign values for a given List defined as a variable in a method. e.g:

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

In the above example, I don't know what to put instead of SOMETHING to make this work. If I put "fooList[0]='....'", it throws an exception complaining there is no fooList property in fooList.

If I put "[0]='....'", it throws Unable to grow collection: unable to determine list element type.

Then I came to define a generic wrapper like this:

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;
    }
}

and then tried to test this one:

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);

But it did not work and still get this ugly message:

Unable to grow collection: unable to determine list element type

I tried other expression languages like MVEL, OGNL, JEXL but I noticed they don't support auto null reference initialization which is important for me. However they did not seem to have a solution around above problem either.

I also started to think what if what I need is not a case for expression languages! The thing is my need is not just defining a variable and try to assign values using an EL.

In my case I have some simple POJO domain class beans and Some input Strings like

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

Now I should be able to create List of Bar and put a Bar instance as its first element, then set foo property with a Foo instance and finally set Foo's value as 3434.

Any idea around this issue?

Thanks in advance

Eit I was wrong in "However they did not seem to have a solution around above problem either". For example in MVEL, this a very easy task to do. But unfortunately the SPLE's ability to auto expanding lists and automatically assigning initiators in null chains makes it incredibly proper for my case.

解决方案

The problem is due to the Type erasure in Java, Spring or other Els don't have a clue to automatically initiate nulls in a chain for generic root objects including Lists. For example in a expression like this in SpEl:

#root[10].mySet='ohoy'

If it detects it needs to initiate the ArrayList first, there is no way of knowing what is the proper element Type to initiate at given index. Thats why it needs a wrapper to use reflection of getter's return type.

Another work through is using an Array. Because arrays component type be kept in runtime. But the catch is arrays can't be resized in runtime. So they need to be initiated with a fairly enough size to prevent index out of range.

Anyway also the Type erasure is a real pain in the ass in order to do these kind of things, seems they (applies other ELs too) still could do some efforts to make some works round this. For example

1) If the list is not empty, it is possible to get the real element's type out of it in runtime.
2) Alter the getValue in order to get the generic type passed parameter and to use it for initiating.
3) In the case of arrays, return the expanded array.
4) ...

Although implementing a good EL that promises handle all kind of initiation or expansion seems a really hard work to do, I was working to extending Ognl to achieve this regards. I started with

PropertyAccessor

and got some really promising results. However, I don't know whats wrong with apache when it comes to develop libraries. For example I don't like the way they put handlers in a Static class. I think a handler is a context matter and yet I don't know if it worth to spend some times in order to extend Ognl, But as soon as I finished the work, I would share the result.

这篇关于如何使用Spring Expression Language(或您知道的其他表达语言)为某些定义为变量的对象的列表分配值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆