我可以在使用JSF 1.2和JSP 2.1的c:forEach标记上的统一EL表达式中使用Hashtable吗?

时间:2008-09-25 22:52:04

标签: java jsp jsf jstl

我有一个Hashtable< Integer,Sport>从我的支持bean中调用sportMap和sportIds列表(List< Integer> sportIds)。 Sport对象具有List< String>设备清单。我可以使用统一的EL来完成以下每项运动的设备清单吗?

<h:dataTable value="#{bean.sportIds}" var="_sportId" > 
  <c:forEach items="#{bean.sportMap[_sportId].equipmentList}" var="_eqp">
    <h:outputText value="#{_eqp}"></h:outputText>
    <br/>
  </c:forEach>
</h:dataTable>

尝试运行此JSP代码时出现以下异常。

 15:57:59,438 ERROR [ExceptionFilter] exception root cause
javax.servlet.ServletException: javax.servlet.jsp.JspTagException: 
      Don't know how to iterate over supplied "items" in &lt;forEach&gt;

这是我的环境打印

Server: JBossWeb/2.0.1.GA
Servlet Specification: 2.5
JSP version: 2.1
JSTL version: 1.2
Java Version: 1.5.0_14

注意:以下操作使用JSF标记。它打印出sportIds列表中指定的每项运动的设备列表。

<h:dataTable value="#{bean.sportIds}" var="_sportId" > 
    <h:outputText value="#{bean.sportMap[_sportId].equipmentList}">
    </h:outputText>
</h:dataTable>

我想使用c:forEach标记。有谁知道这是否可能?如果没有,有人有建议吗?最后我想要一个堆栈列表,而不是equipmentList.toString()提供的逗号分隔列表; (另外,不要覆盖toString())。

3 个答案:

答案 0 :(得分:2)

@ keith30xi.myopenid.com

在JSF 1.2中不为TRUE 。根据{{​​3}},他们应按预期一起工作。

以下是每个常见问题解答的摘录:

  

JSF 1.1常见问题
  问:JavaServer Faces标签是否与JSTL核心标签互操作,forEach,if,choose和when?

     

一个。由于JSTL和JavaServer使用的策略之间不兼容,forEach标记不适用于JavaServer Faces技术,版本1.0和1.1标记   面对技术。相反,您可以使用渲染器,例如dataTable标记使用的表格渲染器,它执行自己的迭代。 if,choose和when标签有效,但嵌套在这些标签中的JavaServer Faces标签必须具有显式标识符。

     

此缺点已在JSF 1.2中修复。

     

JSF 1.2常见问题
  问:JavaServer Faces标签是否与JSTL核心标签互操作,forEach,if,choose和when?

     

一个。是。 JSP 2.1的一个新功能,称为JSP Id Consumer,允许这些标记按预期工作。

有没有人专门为每个人使用带有JSTL核心标签的JSF标签?

答案 1 :(得分:2)

我曾遇到过同样的问题,而且我找不到使用dataTable的解决方案。 问题是var _sportId 只能由dataTable组件读取。

如果需要在循环中进行循环,可以在dataTable中使用dataTable:

<h:dataTable value="#{bean.sportIds}" var="_sportId" > 
  <h:dataTable value="#{bean.sportMap[_sportId].equipmentList}" var="_eqp">
    <h:outputText value="#{_eqp}"></h:outputText>
  </h:dataTable>
</h:dataTable>

但在这种情况下,您的每个设备列表项都打印在表格行中。这不是一个很好的解决方案。

我选择使用普通的html表而不是dataTable:

<table>
    <c:forEach items="#{bean.sportIds}" var="_sportId">
      <tr>
        <td>
        <c:forEach items="#{bean.sportMap[_sportId].equipmentList" var="_eqp">
            <h:outputText value="#{_eqp} " />
        </c:forEach>
        </td>
      </tr>
    </c:forEach>
</table>

有效。如果您需要某些特定的dataTable功能(如绑定和行映射),则可以使用 f:setPropertyActionListener 标记以简单的方式获取它。

答案 2 :(得分:-1)

两个问题:

  1. dataTable只能包含以下子项:标题构面,页脚构面,列。其他任何东西都不会被正确评估。
  2. JSTL标记不能与JSF组件交织。创建组件树时,将评估JSTL标记。在呈现页面时评估JSF组件。因此,c:forEach标记仅被评估一次 - 当创建组件树时,可能在“#{bean.sportIds}”可用之前。
  3. 使用一个JSF组件库来提供你想要的循环,构建一个你想要的循环,或者重构bean,这样就不用循环遍历sportIds,循环遍历每个运动都有它的运动列表身份和设备。