如何防止Seam中的表单重新提交?

时间:2009-11-17 17:53:34

标签: java forms jsf seam

我有一个简单的表格,我不想多次意外提交。

我可以轻松阻止用户在第一次看到该页面时多次点击,但我无法控制他们点击后退按钮。

因此,在使用Struts之后,我决定使用表单提交令牌。

有更简单的方法吗?这个功能已经在Seam中了吗?如果没有,我应该如何在Seam中构建此功能?

//编辑// 只是澄清一下,我不需要能让用户双倍的东西 - 点击。这已经解决了。

具体用例如下: 用户单击该按钮。行动运行。将来一些未指定的时间,用户按下后退按钮足够的时间以使用按钮返回页面。用户再次单击该按钮。

我如何防范?

3 个答案:

答案 0 :(得分:6)

为了避免因不耐烦地按下提交按钮而导致的双重提交,您可以使用一段Javascript,在点击后几毫秒禁用提交按钮。

示例:

<h:commandButton 
    id="foo"
    value="submit"
    action="#{bean.submit}"
    onclick="setTimeout('document.getElementById(\'' + this.id + '\').disabled=true;', 50);"
/>

要避免通过按后退按钮并忽略浏览器警告可能重新发送数据的双重提交,您需要实施Post-Redirect-Get (PRG) pattern

在JSF中,这可以基本上以两种方式完成。在<redirect/>中使用<navigation-case>

<navigation-case>
    <from-action>#{bean.submit}</from-action>
    <from-outcome>success</from-outcome>
    <to-view-id>/page.jsf</to-view-id>
    <redirect/>
</navigation-case>

或通过在bean的action方法中调用ExternalContext#redirect()

public void submit() {
    doYourThing();
    FacesContext.getCurrentInstance().getExternalContext().redirect("page.jsf");
}

唯一的缺点是重定向隐式地创建了一个 new 请求,因此包含了包含其所有属性的初始请求(因此也包括所有请求范围的托管bean和FacesMessages)。在某些情况下它并不重要,但在其他情况下肯定会。我不做Seam,但如果我是正确的,他们已经借助所谓的会话范围解决了这个问题,并通过重定向自动保留FacesMessages。你可以从中受益。

答案 1 :(得分:6)

Seam附带了s:token组件,它正是你要找的: http://docs.jboss.org/seam/2.2.0.GA/reference/en-US/html/controls.html#d0e28933

答案 2 :(得分:2)

使用a4j / RichFaces,使用a4j:队列或为该按钮分配队列。这样,多次点击就会排队,只有一次会真正经过。如果您正在使用RichFaces(我们这样做而不是在任何地方设置队列),为您的应用程序全局设置它的方法是将以下内容放在您的web.xml中:

<context-param>
    <param-name>org.richfaces.queue.global.enabled</param-name>
    <param-value>true</param-value>
</context-param>