我有Home
。每个Home
都有一个Room
列表。每个Room
都有零个或多个Person
s。
我想算一下每个家庭的总人数。但我无法在任何支持bean或实体中添加新变量来记录人数。因此,我只想通过<c:set>
在视图中计算。
我的第一次尝试看起来像:
<c:set var="personCount" value="${0}" />
<ui:repeat var="home" value="#{mybackingBean.homes}">
<ui:repeat var="room" value="#{home.rooms}">
${personCount += room.persons.size()}
</ui:repeat>
<h:panelGrid columns="2">
<h:outputLabel value="#{home.id}" />
<h:outputLabel value="#{personCount}" />
</h:panelGrid>
</ui:repeat>
我怎样才能实现它?
答案 0 :(得分:6)
有几个错误。
首先,
${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中引起同样的问题。
第三,
<c:set>
之类的JSTL标记在视图构建期间运行(从XHTML模板转换为JSF组件树期间)。像<ui:repeat>
这样的JSF组件在视图渲染时间(从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>
有关深入解释,另请参阅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上运行良好。