2011-07-20 44 views
7

我有一個JSP這需要打印是通過採取循環迭代,並將其輸送到另一個對象(春豆),像產生了一些文字:調用JSTL循環中使用參數的方法

<c:forEach var="myVar" items="${myVars}"> 
    <c:out value="anotherObject.getFoo(myVar)"/> 
</c:forEach> 

顯然以上代碼無效,因爲JSTL .運算符只允許無參數調用。我可以看到下面的方法解決這個問題:

1)小腳本

<c:forEach var="myVar" items="${myVars}"> 
    <% 
    SomeType myVar = (SomeType) pageContext.getAttribute("myVar"); 
    SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject"); 
    YetAnotherType result = anotherObject.getFoo(myVar); 
    pageContext.setAttribute("result", result); 
    %> 
    <c:out value="${result}"/> 
</c:forEach> 

明顯CON這裏是JSP代碼污染和一般的醜陋。

2)寫一個標籤,它在scriptlet內部完成任何操作。過度工程的典型例子,yuck!

3)分解的myVars的集合和一個dynamic proxy,其中InvocationHandler會增加額外的參數少的方法來通過anotherObject使所有getFoo()調用替換每個myVar。所有這些都將在控制器中完成,因此JSP將保持乾淨並且myVar保持不變。但在什麼價格?

我不能將.getFoo()方法添加到myVar,因爲它不適合那裏,並會打破關注的分離。

它看起來像在JSP/EL 2.2中可以傳遞參數,但是我使用的是隻包含EL 2.1 API的Tomcat 6.0.29。

問題:任何人都可以提出這種情況最清潔的方法?

回答

2

下面是我在最後做到的。

而不是傳遞一個集合SomeType實例,我傳遞一個地圖。 Map鍵與SomeType相同,值是控制器特定的內部類的實例,我們稱之爲SomeTypeSupplement

SomeTypeSupplement添加必要的無參數吸氣劑並將所有的東西放在一起。 JSP現在迭代映射條目並能夠通過JSTL檢索數據。

這樣我就可以避免Proxy魔術,不必要的TLD,保持JSP的整潔和合理的類型安全。

1

如果你不能遵守腳本(你的替代方案1),我會爲它創建一個自定義標籤(你的替代方案2)或自定義EL功能。我不同意它是「過度工程」,它使用可用的工具達到預期的目的。

你的替代品3雖然我不喜歡。如果有的話,這是過度工程加上它會讓你的系統不必要地複雜和難以讓其他人遵循。堅持你正在工作的規範和標準的意圖。爲了它,不要讓事情變得更難或更復雜。

+3

如果爲每個單獨的方法調用寫一個JSP標記不是過度工程,那麼我不知道過度工程是什麼。我並不是說選項#3是好的/首選的,但都不是#2。 – mindas

+0

好吧,如果你有很多實例需要明確調用JSP中的方法,那麼我建議你改進你的MVC模式,並且努力創建一個只保存數據的清潔模型層。然後將任何邏輯移入Controller層。 – pap

+0

myVar對象就是您稱之爲Model的一個確切示例(僅保存數據的對象 - 在這種情況下爲持久性數據)。然而,我需要可視化的數據來自完全不同的來源(「anotherObject」),並且需要這個模型類。將邏輯移動到Controller層的建議接近我建議的選項#3,並且您說這是一個糟糕的主意。 – mindas

1

爲什麼不在您的後端Java代碼中編寫對象列表,然後使用JSP來顯示它?

+0

我不認爲你已經理解了我所面臨的問題。 '$ {myVars}'已經指向一個對象列表。 – mindas

0

另一種選擇是使用Velocity。它比jstl好得多。

+1

投票選擇一個富有創意的替代方案(我個人首選),但是我們不能總是選擇我們如何獲得視圖 – darkpbj

7

一個簡單的Java只「招修復」,在舊版本的JSTL的作品,也 並且不需要額外的標籤庫/配置/依賴/框架等 是「包裝」您想要的功能來自JSTL 的呼叫從Map類擴展而來,並覆蓋其get()方法。

作爲最簡單的例子,想從JSTL,調用Math.sin()功能 你會定義一個類:在你的行動

public class Sine extends HashMap<Double, Double> { 
    private static final long serialVersionUID = 1L; // Avoids compiler-warning 

    @Override 
    public Double get(Object arg) { 
     Double x = (Double) arg; 
     return Math.sin(x); 
    } 
} 

然後execute()方法,你這樣做:

... 
request.setAttribute("sine", new Sine()); 
... 

然後在JSP中,你可以說:

${sine[0.75]} 

計算值Math.sin(0.75)

JSTL會將可變正弦對待爲Map,但您可以使用get()方法計算並返回任何您喜歡的東西。

我想它變得有點更復雜,如果你有一個以上的參數的功能, 但應該有針對的解決方法,太:)

+1

有趣的方法,感謝分享! – mindas

+1

非常好,非常感謝,非常感謝。對於那些在這些東西中是新的modelAndView.addObject(「sine」,new Sine());相當於request.setAttribute(「sine」,new Sine())的spring MVC版本; – HaMi

1

誠徵添加註釋到最後(按時間)Rop的答案,但缺少「聲譽」,所以在這裏我有一個答案。

我很快與這樣的地圖有相同的想法,但試圖使它更通用,有一個「動態地圖」,DynamicMapCalculator接口,並讓您將任何方法調用包裝到這樣的地圖中(無需製作新的地圖實現,每次只使用匿名類實例)。

這將是主題,如果你有興趣: A qu. of style: dynamic map JSTL hack to work around missing parameter function calls

而且我會感興趣的意見有:是這樣的東西,你可以不內疚嗎?