2012-04-10 77 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