有几个错误。
First,
${personCount += room.persons.size()}
在 EL 中,+=
is the 字符串连接运算符 http://docs.oracle.com/javaee/7/tutorial/jsf-el005.htm#BNAIK。所以,这基本上会给你结果String.valueOf(personCount) + String.valueOf(size)
。如果计数初始化为0
并且有3
人,那么这将打印03
.
您基本上想重新分配结果personCount + size
返回变量personCount
。您需要使用重新设置变量<c:set>
如下。
<c:set var="personCount" value="${personCount + room.persons.size()}" />
Second,
<c:set var="personCount" value="${0}" />
<[for each home]>
<[for each room]>
<c:set var="personCount" value="${personCount + room.persons.size()}" />
The personCount
初始化为0
在两次迭代之外。因此,对于每个家庭,您也可以通过这种方式计算之前所有家庭的人数。您想在第一次迭代中声明它。
<[for each home]>
<c:set var="personCount" value="${0}" />
<[for each room]>
<c:set var="personCount" value="${personCount + room.persons.size()}" />
这与 EL 无关。这只是一个逻辑错误,在“plain vanilla”Java 中也会导致同样的问题。
Third,
JSTL 标签如<c:set>
在视图构建期间(从 XHTML 模板转换为 JSF 组件树期间)运行。 JSF 组件如<ui:repeat>
在视图渲染期间(从 JSF 组件树转换为 HTML 输出期间)运行。所以<c:set>
期间不运行<ui:repeat>
迭代。因此,它看不到迭代变量var
。您基本上还需要在视图构建期间进行迭代。你可以使用JSTL<c:forEach>
为了这。
因此,总而言之,您的预期解决方案如下所示:
<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>
有关深入的解释,另请参阅JSF2 Facelets 中的 JSTL...有意义吗? https://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense
然而,作为+=
运算符显然不会在您的情况下导致 EL 异常,这意味着您已经在使用 EL 3.0。这反过来意味着您可以使用新的EL 3.0 lambda 和流功能 http://docs.oracle.com/javaee/7/tutorial/jsf-el004.htm.
<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 上运行。