熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

解決jsp重復提交

2013-11-15 11:53:50  來源: JSP教程 

  有幾種方法
在你的表單頁裡HEAD區加入這段代碼:
<META HTTPEQUIV="pragma" CONTENT="nocache">
<META HTTPEQUIV="CacheControl" CONTENT="nocache mustrevalidate">
<META HTTPEQUIV="expires" CONTENT="Wed Feb :: GMT">

生成一個令牌保存在用戶session中在form中加一個hidden域顯示該令
牌的值form提交後重新生成一個新的令牌將用戶提交的令牌和session
中的令牌比較如相同則是重復提交

在你的服務器端控件的代碼中使用ResponseRedirect("selfPage")語句但是大多的數都不使用這種方法
方法還有很多

<input type="button" value="提交" onclick="thisdisabled=true;thisformsubmit()">

  

  在JSP頁面的FORM表單中添加一個hidden域
<input type="hidden" name="url"value=<%=requestgetRequestURL()%>>

在你的serverlet中添加如下語句
String url=requestgetParameter("url");
responsesendRedirect(url);
我一般都是采用這樣的方法返回JSP頁面的不太明白你說的重復刷新是什麼概念

   ajax 無刷新提交

   Web開發中防止浏覽器的刷新鍵引起系統操作重復提交
怎麼解決呢?重定向可以解決頁面刷新帶來的數據的重復提交的問題我們自然可以利用重定向的方式來解決這個問題但是struts的action裡面mappingfindword()跳轉的話默認的是在工程文件夾裡面找要跳轉的頁面這種情況怎麼解決呢?
修改struts-configxml 文件 在action裡面有一個redirect重新定向的屬性struts中默認的是false添加這個屬性改成true在forword中寫上要跳轉頁面的絕對或者相對地址就行了
修改如下
<actionmappings>
<action attribute="newsActionForm" name="newsActionForm"
input="/addnewsjsp" path="/newsAction" parameter="method"
scope="request" type="comyongtreenewsactionNewsAction">
<forward name="list" path="/listnewsjsp" redirect="true"></forward>
<forward name="error" path="/addnewsjsp"></forward>
</action>
</actionmappings>
重復提交重復刷新防止後退的問題以及處理方式

  一前言
你在任何一個比較專業的BBS都會看到這樣的問題即使你Google一下也會發現有很多的人在關注和詢問但大家給出的解決方法卻都是千差萬別(有的人主張采用腳本來解決;有的則想重定向到別的頁面;有的則將此問題提升到Token的角度)為什麼會有如此大的差異呢?

  二問題場景
首先我們應該先了解為什麼要處理這樣的問題?或者專業一點就是它適合的場景是什麼?(似乎只有人來問沒有人來解釋)

  重復提交重復刷新的場景
重復提交重復刷新都是來解決系統重復記錄的問題也就是說某個人在多次的提交某條記錄(為什麼?也許是閒了沒有事情干的;最有可能是用戶根本就不知道自己的提交結果是否已經執行了?!)

  但出現了這樣的問題並不見得就必須處理要看你所開發的系統的類別而定比如你接手的是某個資源管理系統系統本身從需求的角度根本就不允許出現"重復"的記錄在這樣需求的約束條件下去執行重復的提交動作只會引發“業務級異常”的產生根本就不可能執行成功也就無所謂避免不避免的問題了

  防止後退的場景
了解了重復刷新重復提交的場景我們來了解一下"防止後退"操作的原因是什麼?比如你在開發某個投票系統它有很多的步驟並且這些步驟之間是有聯系的比如第一步會將某些信息發送給第二步第二步緩存了這些信息同時將自身的信息發送給了第三步等等如果此時用戶處在第三步驟下我們想象一下某個淘氣用戶的用戶點擊了後退按鈕此時屏幕出現了第二步驟的頁面他再次的修改或者再次的提交進入到下一個步驟(也就是第三步驟)錯誤就會在此產生?!什麼錯誤呢?最為典型的就是這樣的操作直接導致了對於第一個步驟信息的丟失!(如果這樣的信息是依靠Request存放的話當然你可以存放在Session或者更大的上下文環境中但這不是個好主意!關於信息存放的問題下次在就這個問題詳細的討論)

  
如何處理的問題
當然很多的系統(比如訂票系統從需求上本身是允許個人重復訂票的)是必須要避免重復刷新重復提交以及防止後退的問題的但即使是這樣的問題也要區分如何處理以及在哪裡處理的(網上只是告訴你如何處理但很少去區分在哪裡處理的)顯然處理的方式無非是客戶端或者服務器端兩種而面對不同的位置處理的方式也是不同的但有一點要事先聲明任何客戶端(尤其是B/S端)的處理都是不可信任的最好的也是最應該的是服務器端的處理方法

  客戶端處理
面對客戶端我們可以使用Javascript腳本來解決如下

  重復刷新重復提交
Ways One設置一個變量只允許提交一次
<script language="javascript">
var checkSubmitFlg = false;
function checkSubmit() {
if (checkSubmitFlg == true) {
return false;
}
checkSubmitFlg = true;
return true;
}
documentondblclick = function docondblclick() {
windoweventreturnValue = false;
}
documentonclick = function doconclick() {
if (checkSubmitFlg) {
windoweventreturnValue = false;
}
}
</script>
<html:form action="myActiondo" method="post" onsubmit="return checkSubmit();">

  Way Two : 將提交按鈕或者image置為disable
<html:form action="myActiondo" method="post"
onsubmit="getElById(submitInput)disabled = true; return true;">
<html:image styleId="submitInput" src="images/ok_bgif" border="" />
</html:form>

  防止用戶後退
這裡的方法是千姿百態有的是更改浏覽器的歷史紀錄的比如使用windowhistoryforward()方法;有的是“用新頁面的URL替換當前的歷史紀錄這樣浏覽歷史記錄中就只有一個頁面後退按鈕永遠不會變為可用”比如使用javascript:locationreplace(thishref); eventreturnValue=false;

  
服務器端的處理(這裡只說Struts框架的處理)
利用同步令牌(Token)機制來解決Web應用中重復提交的問題Struts也給出了一個參考實現

  基本原理
服務器端在處理到達的請求之前會將請求中包含的令牌值與保存在當前用戶會話中的令牌值進行比較
看是否匹配在處理完該請求後且在答復發送給客戶端之前將會產生一個新的令牌該令牌除傳給
客戶端以外也會將用戶會話中保存的舊的令牌進行替換這樣如果用戶回退到剛才的提交頁面並再次
提交的話客戶端傳過來的令牌就和服務器端的令牌不一致從而有效地防止了重復提交的發生

  if (isTokenValid(request true)) {
// your code here
return mappingfindForward("success");
} else {
saveToken(request);
return mappingfindForward("submitagain");
}

  Struts根據用戶會話ID和當前系統時間來生成一個唯一(對於每個會話)令牌的具體實現可以參考
TokenProcessor類中的generateToken()方法

   //驗證事務控制令牌<html:form >會自動根據session中標識生成一個隱含input代表令牌防止兩次提交
在action中

  
//<input type="hidden" name="orgapachestrutstaglibhtmlTOKEN"
// value="aaffdcccae">
if (!isTokenValid(request))
errorsadd(ActionErrorsGLOBAL_ERROR
new ActionError("errortransactiontoken"));
resetToken(request); //刪除session中的令牌

   action有這樣的一個方法生成令牌
protected String generateToken(HttpServletRequest request) {
HttpSession session = requestgetSession();
try {
byte id[] = sessiongetId()getBytes();
byte now[] =
new Long(SystemcurrentTimeMillis())toString()getBytes();
MessageDigest md = MessageDigestgetInstance("MD");
mdupdate(id);
mdupdate(now);
return (toHex(mddigest()));
} catch (IllegalStateException e) {
return (null);
} catch (NoSuchAlgorithmException e) {
return (null);
}
}

  總結
對於重復提交重復刷新防止後退等等都是屬於系統為避免重復記錄而需要解決的問題在客戶端去處理需要針對每一種的可能提出相應的解決方案然而在服務器端看來只不過是對於數據真實性的檢驗問題基於令牌的處理就是一勞永逸的方法


From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19842.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.