提交应在呈现响应时使用 javascript 禁用所有按钮。
这是最容易以通用方式实现的。如果您碰巧<f:ajax>
专门使用,您可以使用jsf.ajax.addOnEvent()
以通用方式执行工作。另一种 JavaScript 方法是创建一种“正在加载”的覆盖层,它会阻止 UI,这样最终用户将无法再与底层页面进行交互。这基本上是一个绝对定位的隐藏,它以一些(透明度)<div>
跨越整个视口。opacity
您可以在提交时显示它并在渲染时隐藏它。这种技术的关键词是“模态对话”。面向 UI 的 JSF 组件库中至少有这样一个组件。例如PrimeFaces<p:dialog modal="true">
里面有 a ,<p:ajaxStatus>
或者<p:blockUI>
唯一的缺点是,如果客户端禁用了 JS 或不使用它,它将无法工作,因此不会阻止 HTTP 客户端重复提交。
Session 范围中的一个标志表明它已经处于活动状态,因此敏感代码被跳过并继续重新呈现上一次提交的响应。
这更多地被称为“同步器令牌模式”,并且曾经被规范问题 559要求为 JSF,该问题目前在针对 2.2 的票证上,但似乎没有任何活动。检测和阻塞部分在技术上很容易实现,但是如果您希望最终用户最终检索到初始请求生成的响应,则同步响应处理部分就不容易实现。异步响应处理很简单:只需不指定任何要更新的组件,即清空由PartialViewContext#getRenderIds()
. 毕竟,这比使用 JS 禁用按钮或阻塞 UI 更健壮。
据我所知,Seam 2是唯一为此提供可重用 JSF 组件的,<s:token>
. 然而,我必须承认,对于一个新的OmniFaces组件来说,这是一个有趣的想法。也许我会亲自去看看。
延迟处理直到前一个请求完成的同步块。然后应该检测到它已经被处理并跳过了。
这通常不容易实现,这需要更改所有操作方法以检查工作是否已经完成。如果 webapp 在多个服务器上运行,它也将不起作用。同步器令牌更容易,因为它会在调用操作方法之前执行。同步器令牌也更便宜,因为您最终不会在队列中出现多个请求,这只会花费线程/资源。
使用转换之类的“新”范围之一来处理检测?
这个问题不能通过使用托管 bean 范围来解决。托管 bean 作用域有不同的用途:bean 实例的生命周期。