2015-02-11 20 views
0

在Spel中,爲List屬性分配一些值很容易。 例如具有定義爲列表屬性對象foo,我通常會做:如何使用Spring表達式語言(或您知道的其他表達式語言)爲定義爲變量的對象列表賦值

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

在上面的例子中,我不知道該怎麼做,而不是使用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但我注意到它們不支持aut o null參考初始化對我很重要。然而,他們似乎也沒有解決上述問題的方法。

我也開始思考如果我需要的不是表達式語言的情況! 事情是我的需要不只是定義一個變量,並嘗試使用EL分配值。

在我的情況,我有一些簡單的POJO域類豆類和一些輸入字符串像

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

現在我應該能夠創建欄的列表,並把一個酒吧實例作爲其第一個元素,然後設置FOO財產與Foo實例並最終將Foo的值設置爲3434.

圍繞此問題的任何想法?

在此先感謝

EIT 我「不過,他們似乎並沒有圍繞有上述問題的解決方案要麼」是錯誤的。例如在MVEL中,這是一個非常容易的任務。但不幸的是,SPLE能夠自動擴展列表並自動分配空鏈中的啓動器,這使得它非常適合我的情況。

回答

0

這個問題是由於Java中的類型擦除,Spring或其他Els沒有線索自動啓動通用根對象(包括列表)的鏈中的空值。 例如在SPEL這樣的表達:

#root[10].mySet='ohoy' 

如果它檢測到它需要首先發起的ArrayList中,有沒有知道什麼是正確的元素類型發起在給定的索引方式。 這就是爲什麼它需要一個包裝來使用getter的返回類型的反射。

另一項工作是使用數組。因爲數組組件類型被保留在運行時。但是捕獲是數組在運行時無法調整大小。 因此,他們需要以足夠大的尺寸啓動,以防止索引超出範圍。

無論如何,類型擦除是爲了做這些事情的屁股真正的痛苦,似乎他們(也適用於其他ELs)仍然可以做一些努力,使一些工作圍繞此。例如

1)如果列表不是空的,可以在運行時從中獲取真實元素的類型。
2)改變getValue以獲得通用類型傳遞的參數並將其用於啓動。
3)對於數組,返回展開的數組。
4)...

雖然實施一個好的EL承諾可以處理所有類型的啓動或擴展似乎是一個非常艱苦的工作,但我正在努力擴展Ognl來實現這一點。我開始於

PropertyAccessor 

並得到了一些非常有希望的結果。但是,當我們開發庫時,我不知道Apache有什麼問題。例如,我不喜歡他們將處理程序放在Static類中的方式。我認爲一個處理程序是一個背景問題,但我不知道爲了擴展Ognl是否值得花費一些時間,但只要我完成了這個工作,我會分享結果。

0

您必須在您的表達式中定義一個變量並將其填入要處理的列表中,

context.setVariable("mylist", fooList); 

然後你就可以像這樣訪問:

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

在變量列表用於反射;你可以調用方法等。 我希望這有助於。

+0

謝謝@Uwe Aliner的回答。但是我對這個解決方案有幾個問題。 1)擁有context = new StandardEvaluationContext();然後context.setVariable(「fooList」,fooList);最後解析器=新的SpelExpressionParser(config); parser.parseExpression(「#fooList.set(0)='ooooooo'」) \t \t .getValue(context);拋出這個異常:'類org.springframework.expression.spel.ast.MethodReference'不支持'setValue(ExpressionState,Object)' – madz 2015-02-11 17:55:14

+0

2)我可以不定義一個變量,並設置上下文後,只要做:「#root [0] = 'OOOOO'」。它拋出的問題無法索引到一個空值。然後使上下文能夠自動擴展列表(使用SpelParserConfiguration)再次使其失敗,無法增長集合:無法確定列表元素類型 – madz 2015-02-11 18:04:50

+0

如果我自己在第一個解決方案中擴展列表,問題就解決了。但是由於表情的緣故,(我不能操縱表情來源,他們就是這樣,我只能在得到它們後才能改變它們。例如通過正則表達式)我想看看是否有辦法用簡單的EL解決方案來解決這個問題,並且不要讓我的手油膩;) – madz 2015-02-11 18:16:59