有幾個錯誤。
首先,
${personCount += room.persons.size()}
在EL中,+=
是string concatenation operator。所以,這會給你基本上String.valueOf(personCount) + String.valueOf(size)
的結果。如果計數初始化爲0
並且有3
個人,則將打印03
。
您基本上想要將personCount + size
的結果重新分配回變量personCount
。您需要使用<c:set>
重新設置變量,如下所示。
<c:set var="personCount" value="${personCount + room.persons.size()}" />
其次,
<c:set var="personCount" value="${0}" />
<[for each home]>
<[for each room]>
<c:set var="personCount" value="${personCount + room.persons.size()}" />
personCount
該被初始化爲0
兩者的迭代之外。所以,對於每個家庭來說,你也可以通過這種方式來計算以前所有家庭的人數。你想在第一次迭代中聲明它。
<[for each home]>
<c:set var="personCount" value="${0}" />
<[for each room]>
<c:set var="personCount" value="${personCount + room.persons.size()}" />
這不是EL相關。這只是一個邏輯錯誤,它也會導致「普通香草」Java中出現同樣的問題。
第三,
JSTL標記等(從XHTML模板來JSF組件樹轉換期間)期間視圖編譯時間<c:set>
運行。 JSF組件(如<ui:repeat>
)在視圖呈現時(在從JSF組件樹轉換爲HTML輸出期間)運行。因此,<c:set>
在<ui:repeat>
迭代期間不運行。因此,它看不到迭代變量var
。您基本上也需要在查看構建時間內迭代。您可以使用JSTL <c:forEach>
。
所以,一切的一切,你intented的解決方案是這樣的:
<c:forEach items="#{bean.homes}" var="home">
<c:set var="personCount" value="${0}" />
<c:forEach items="#{home.rooms}" var="room">
<c:set var="personCount" value="${personCount + room.persons.size()}" />
</c:forEach>
<h:panelGrid columns="2">
<h:outputLabel value="#{home.id}" />
<h:outputLabel value="#{personCount}" />
</h:panelGrid>
</c:forEach>
有關深入的解釋,另見JSTL in JSF2 Facelets... makes sense?
然而,隨着+=
運營商顯然不會在您的情況下會導致EL異常,這意味着您已經在使用EL 3.0。這反過來意味着你可以使用新的EL 3.0 lambda and stream features。
<ui:repeat value="#{bean.homes}" var="home">
<h:panelGrid columns="2">
<h:outputLabel value="#{home.id}" />
<h:outputLabel value="#{home.rooms.stream().map(room -> room.persons.size()).sum()}" />
</h:panelGrid>
</ui:repeat>
不再需要計數循環。不,這不需要Java 8,它可以在Java 7上工作。