在JSF中刷新时避免两次创建相同的对象

时间:2009-08-27 06:35:42

标签: jsf

假设我们在AddObject.jspx中有一个“添加新对象”表单,并且有一个Confirm.jsp页面(类似ID为NN的对象被添加到数据库中......)

在faces-config.xml中:

<navigation-rule>
    <from-view-id>/AddObject.jsp</from-view-id>
    <navigation-case>
        <from-outcome>add</from-outcome>
        <to-view-id>/Confirm.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

因此,用户打开AddObject.jsp,填写表单,然后单击“添加”按钮,该按钮触发AddObject的辅助bean中的事件处理程序。支持bean将新对象插入数据库并返回“添加”结果。所以我们最终进入确认屏幕。

现在,如果我点击F5(刷新浏览器),将创建一个新对象,并使用新对象的新ID重新显示“确认”屏幕。我可以继续按F5并获得尽可能多的新对象。

我不想要这个。我想检测这种情况。避免多次添加同一个对象(在数据库中生成许多只有ID不同的行)。

我可以用JSF做到这一点吗?如果它似乎没有充分利用这些信息,它为什么要求我提供from-view-id / outcome / to-view-id?

1 个答案:

答案 0 :(得分:3)

这个问题有两个部分。

首先,您需要避免让broswer刷新确认页面重新提交请求。因此,如果对于布鲁尔的历史而言,一种方法就是不说

 POST this request

而是说

 GET this confirmation page

我们可以使用

来做到这一点
 <redirect/>
JSF导航中的

语句。现在这意味着重定向响应被发送到浏览器。然后浏览器向JSF询问构造页面。注意:现在这是来自JSF视角的新请求,因此您要显示的任何数据都需要处于会话范围而不是请求范围。

这种“使用重定向进行更改的操作”方法是一种非常常见的习惯用法。但是它没有解决“Quick Fire User”问题。如果用户非常快速地点击“提交”两次会发生什么?您可以到达浏览器发送了两个请求的情况。还有其他可能发生这种情况的情况 - 第一次请求时网络故障,用户不耐烦,再次发送请求。

所以我们需要以某种方式处理这样的双重提交。这不是JSF特有的问题。典型的解决方案是后端在填充原始请求页面时发送令牌。这是在隐藏的领域举行。提交请求时,将令牌(某个唯一号码)发送回记录已使用的应用程序,因此会检测到双重提交。

您还可以在浏览器中使用JavaScript来防止双重提交。这应该提供更友好的用户体验,但我不建议仅依赖于浏览器端控件。服务器应具有最终的可响应性。