天天看點

Struts2架構學習之七:避免表單重複送出

前言

防止表單重複送出在web開發中是一個經常遇到的問題,一般來避免重複送出有兩種方式:用戶端javascript代碼實作和服務端代碼實作。這裡主要介紹服務端的實作方式。在服務端實作表單重複送出的基本原理是:通過建立一個session對象,并産生一個令牌值,将這個令牌值作為隐藏域随表單一起發送給用戶端,同時在session中儲存令牌值。在使用者送出表單的時候判斷送出參數的令牌值與session中的是否相等,如果相等則清除,不再使用這個令牌值,,然後執行後續的處理;如果兩者不相等,表示已經送出過表單,服務端産生一個新的令牌值并儲存到session中。當使用者下次通路的的時候,将新産生的領牌值發送到用戶端。

struts2的實作方式

在struts2中通過使用攔截器來實作的,機制與前言中采用令牌的方式是一樣的。可以通過兩種方式實作避免重複表單(實際上就是兩個不同的攔截器):token攔截器和tokensession攔截器。由于在struts-default.xml的預設攔截器棧中并沒有将這兩個攔截器作為預設實作,是以需要在action中手動添加這兩個攔截器。這兩種方式的差別在于:使用token攔截器重複送出表單的時候,浏覽器會跳轉到一個錯誤頁面,而使用更tokensession攔截器重複送出表單的話是不會跳轉的,仍然在成功之後頁面。需要注意的是,使用者兩個攔截器重複送出表單的時候,都隻會向伺服器送出一次請求,是以這種方式可以有效降低伺服器的負擔。

具體的例子

在使用以上攔截器進行測試的時候,需要如下步驟:

步驟一:編寫login.jsp、success.jsp和error.jsp三個頁面

login.jsp

success.jsp

error.jsp

步驟二:編寫action

步驟三:配置struts.xml

這裡需要提出的是,action中name屬性為<code>invalid.token</code>的result是不可少的。

步驟四:釋出測試

經過測試,發現使用token攔截器在重複送出表單的時候會轉到error.jsp,而使用tokensession攔截器在重複送出表單的時候不會轉到error.jsp。

顯示等待頁面

有時候在action需要處理較長時間的時候,一般是5到10分鐘,在這種情況下向使用者顯示一個等待頁面可能會比較友好一些。在struts2中通過使用execandwait攔截器就可以非常輕松實作這點。

execandwait的工作機制:

execandwait攔截器能夠讓一個a執行時間超過5分鐘的action在背景運作,并向使用者顯示一個等待頁面。之是以是5分鐘是因為這樣防止http請求逾時。當一個請求到來的時候,execandwait攔截器會建立一個線程來執行session,然後傳回一個等待頁面,這樣使用者就知道請求在進行中。等待頁面包含了自動重新整理功能,在逾時之前,浏覽器會向初始請求的action再次發起請求,以便知道背景action是否已經執行完畢。如果action仍然沒有執行完畢,則繼續顯示等待頁面,如果action已經執行完畢,則等待頁面将發生跳轉,向使用者處理結束之後的頁面。

execandwait攔截器有以下幾個參數:

threadpriority:執行線程的優先級

delay:指定在顯示等待頁面前初始的延遲加載時間,機關是毫秒

delaysleepinternal:指定檢查背景線程是否執行完畢的時間間隔,必須和delay參數一起使用,機關是毫秒,預設是100毫秒。表示每100毫秒進行一次檢查

使用execandwait攔截器顯示等待頁面,首先需要編寫一個等待頁面:

在head 标簽中需要添加自動重新整理meta标簽,不然是不會出發自動檢查的。在這個等待頁面中,表示3秒後就會跳轉到成功頁面。

之後是添加execandwait攔截器的配置:

注意到tokenaction類中,使用tread.sleep(3000),表示通過讓線程休眠的方式延長action的處理時間,還有一點要注意的是struts.xml中execandwait攔截器的delay參數的值需要小于thread.sleep(time)的時間。這樣就能保證在action處理結束之前完成顯示等待頁面,不然很可能會直接success.jsp頁面了。

繼續閱讀