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ライフサイクルの最終段階である場合、「応答のデコード」はどこに当てはまりますか?それらは、次のポストバックREQUEST(行、したがって名前オブジェクトを識別するために生成されたIDを送信する)のデコードを意味しますか?

そして:どうすればこれをより堅牢な方法で実装できますか?

4

1 に答える 1

2

メソッド式は、フォームの表示要求(本が話しているエンコードステップ)ではなく、フォーム送信の処理要求(本が話しているデコードステップ)で評価されます。データテーブル行の入力とアクションは、テーブルの行インデックスに基づいて決定されます。フォーム送信の処理中に、JSFは、送信された値と呼び出されたアクションを見つけるために、データモデルを繰り返し処理します。

したがって、<h:dataTable value>がリクエストスコープのBeanに関連付けられているため、データモデルがリクエストごとに再初期化される場合、フォーム送信の処理中に間違ったインデックスでアイテム#{item}実際に参照するリスクがあります。フォームを表示してフォームを送信するリクエストの場合、DBは新しいアイテムを取得したか、別のアイテムを削除した可能性があります。これにより、目的のアイテムが別のインデックスに移動する可能性があります。

これを回避するには、Beanをビュースコープに配置して、最初のリクエストの(ポスト)コンストラクターで初期化されたものとまったく同じデータモデルが、すべてのリクエストの開始時に再初期化する必要なしに、ポストバック間で保持されるようにする必要があります。したがって、異なるアイテムまたは異なる順序で含まれる可能性があります。データモデルの読み込みが、検索クエリのようにエンドユーザーの完全な制御下にある特定のリクエストパラメータに関連付けられている場合、影響はさらに大きくなります。

この特定の非べき等の「このアイテムを削除」の場合には実際には悪いものですが、べき等の「このアイテムを編集する」場合には良い代替方法は、代わりにGETリンクを使用することです。目的のアイテムは、要素のクエリ文字列パラメータとしてすぐにレンダリングされます<a>

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