3

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 生命周期的最后阶段,那么“解码响应”在哪里适合?它们是否意味着解码以下回发请求(发送生成的 ID 以识别行并因此识别名称对象)?

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

4

1 回答 1

2

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

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

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

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

<h:link value="Edit" outcome="edit">
    <f:param name="id" value="#{item.id}" />
</h:link>
于 2013-03-25T16:06:32.170 回答