将数据表对象var作为EL表达式中的参数传递:如何使其健壮?

时间:2013-03-25 15:44:17

标签: jsf datatable el page-lifecycle

Core JavaServer Faces中,我们找到以下用于从DataTable中删除行的示例,其中tableData.names是Name对象的列表:

<h:dataTable value="#{tableData.names}" var="name" ... />    
    <h:commandLink value="Delete" action="#{tableData.deleteRow(name)}" /> 
</h:dataTable>

它附带一个警告,如果我们使用请求范围并且列表在“表的呈现和响应的解码之间”之间发生更改,则可能不会删除正确的行。

  

注意:如果数据表的值具有请求范围,请确保数据在表的呈现和响应的解码之间不会发生变化   (第3版第226页)

任何人都可以根据JSF生命周期来解释这个引用吗?如果“渲染响应”是JSF生命周期的最后阶段,那么“解码响应”适合哪里?它们是否意味着解码以下回发REQUEST(它发送生成的ID来识别行,从而识别名称对象)?

并且:我们如何以更强大的方式实现这一点?

1 个答案:

答案 0 :(得分:2)

在显示表单的请求期间(在书正在讨论的编码步骤)期间不评估方法表达式,但是在处理表单提交的请求期间(本书所讨论的解码步骤)。数据表行的输入和操作是根据表的行索引确定的。在处理表单提交期间,JSF重新遍历数据模型,以便查找提交的值和调用的操作。

因此,如果<h:dataTable value>与请求范围的bean相关联,因此基于每个请求重新初始化数据模型,那么您将冒#{item} 实际< / em>在处理表单提交期间引用错误索引处的项目,因为在显示表单和提交表单的请求之间,数据库可能已检索到新项目,或已删除了另一项可能会移动期望的项目到不同的索引。

为了避免这种情况,需要将bean放在视图范围中,以便在回发中保留在初始请求的(post)构造函数中初始化的完全相同的datamodel,而无需在开始时重新初始化它。每个请求,因此可能包含不同的项目或不同的顺序。如果在完全控制最终用户(如搜索查询)的情况下将数据模型的加载与特定请求参数绑定,则影响会更大。

另一种选择,在这个特殊的非幂等“删除此项目”案例中实际上是一个不好的选择,但对于幂等“编辑此项目”案例来说,这是一个很好的选择,而是使用GET链接。所需项目立即呈现为<a>元素的查询字符串参数。

<h:link value="Edit" outcome="edit">
    <f:param name="id" value="#{item.id}" />
</h:link>