假设我们在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?
答案 0 :(得分:3)
这个问题有两个部分。
首先,您需要避免让broswer刷新确认页面重新提交请求。因此,如果对于布鲁尔的历史而言,一种方法就是不说
POST this request
而是说
GET this confirmation page
我们可以使用
来做到这一点 <redirect/>
JSF导航中的语句。现在这意味着重定向响应被发送到浏览器。然后浏览器向JSF询问构造页面。注意:现在这是来自JSF视角的新请求,因此您要显示的任何数据都需要处于会话范围而不是请求范围。
这种“使用重定向进行更改的操作”方法是一种非常常见的习惯用法。但是它没有解决“Quick Fire User”问题。如果用户非常快速地点击“提交”两次会发生什么?您可以到达浏览器发送了两个请求的情况。还有其他可能发生这种情况的情况 - 第一次请求时网络故障,用户不耐烦,再次发送请求。
所以我们需要以某种方式处理这样的双重提交。这不是JSF特有的问题。典型的解决方案是后端在填充原始请求页面时发送令牌。这是在隐藏的领域举行。提交请求时,将令牌(某个唯一号码)发送回记录已使用的应用程序,因此会检测到双重提交。
您还可以在浏览器中使用JavaScript来防止双重提交。这应该提供更友好的用户体验,但我不建议仅依赖于浏览器端控件。服务器应具有最终的可响应性。