2012-04-10 75 views
10

据测试报告,如果响应速度不够快,有时可能会多次按下按钮,导致后端代码的多次调用,这是我们不想要的。如何在呈现响应之前处理多个提交?

应用程序是Glassfish 3.1.1内部使用JSF 2.0的Java EE 6 Web Profile。

我想,这应该是妥善处理,并认为有几个可能性:

  • 提交应该禁止使用JavaScript,而响应所呈现的所有按钮。
  • 会话范围中的一个标志表明它已处于活动状态,因此敏感代码将被跳过,并转至重新呈现之前提交的响应。
  • 延迟处理直到前一个请求完成的同步块。然后应该检测到它已被处理并跳过。
  • 使用转换等“新”范围之一来处理检测?

我的直觉是最好的方法是让敏感的代码块原子化,但问题是呈现正确的响应。

我该如何解决这个问题?

+0

你尝试过类似jQuery blockui的东西吗? BTW同步块在集群上不起作用。 – 2012-04-10 12:15:55

+0

还没有试过。这是在“那么,我该怎么做?”阶段。 – 2012-04-10 12:58:09

回答

2

正如Adrian所说,我也会使用BlockUI。 Primefaces有BlockUI component。当您通过ajax提交表单时,您也可以在请求期间使用覆盖。以Primefaces的Ajax Status为例。

10

正在呈现响应时,提交应该禁用所有使用javascript的按钮。

这是以通用方式实现的最容易的方式。如果您恰好使用<f:ajax>,则可以使用jsf.ajax.addOnEvent()以通用方式执行该作业。另一种JavaScript方法是创建一种“加载”覆盖图,以阻止用户界面,以便最终用户不能再与底层页面进行交互。这基本上是一个绝对定位隐藏<div>其中跨越整个视口与一些opacity(透明度)。您可以在提交时显示它并将其隐藏在渲染上。该技术的关键字是"modal dialog"。面向UI的JSF组件库至少有一个这样的组件已经在它们的组合中。例如。 PrimeFaces<p:dialog modal="true">一个<p:ajaxStatus>内,或<p:blockUI>

唯一的缺点是,它不会在客户端已禁用JS或工作不使用它,因此,它不会阻止HTTP客户端双重的提交。


在Session范围的标志说这已经是活动的,所以敏感代码被跳过,只是移动到响应的重新渲染为前提交。

这更是被称为"synchronizer token pattern"和曾经被spec issue 559这也是目前针对2.2的票请求JSF,但似乎并没有被它的任何活动。检测和阻塞部分在技术上很容易实现,但如果您希望最终用户最终检索由初始请求生成的响应,则同步响应处理部分不易实现。异步响应处理非常简单:只要不指定任何组件即可进行更新,即清空PartialViewContext#getRenderIds()返回的集合。毕竟,这比使用JS来禁用按钮或阻止UI更强大。

据我所知,Seam 2是唯一一个为此提供可重复使用的JSF组件的<s:token>。但是,我必须承认,对于新的OmniFaces组件,这是一个有趣的想法。也许我会亲自看看它。


同步的块延迟的处理,直到先前的请求已经完成。然后应该检测到它已被处理并跳过。

这一般不易实现,这需要更改所有操作方法来检查作业是否已完成。如果Web应用运行在多个服务器上,它也不起作用。同步器标记更容易,因为它将在调用操作方法之前执行。同步器令牌也较便宜,因为您不会在队列中产生多个请求,而这些请求只会花费线程/资源。


使用“新”的范围像转换处理的检测吗?

玩弄托管bean作用域无法解决此问题。托管bean作用域的用途不同:bean实例的生命周期。

+0

除了“synchronized block”之外,你还可以看看这个过滤器 - http://onjava.com/onjava/2004/03/24/examples/RequestControlFilter.java – 2012-04-10 18:05:10

+0

谢谢你提供一个非常丰富的答案。你有没有想到我自己的其他建议? – 2012-04-12 11:26:33

+0

不客气。不,除了使用JS来禁用/阻止用户交互,或使用同步器令牌模式之外,没有其他方法。 – BalusC 2012-04-12 12:54:25