周游世界

          喂馬, 劈柴, 周游世界

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            28 隨筆 :: 0 文章 :: 4 評論 :: 0 Trackbacks
          B/S結(jié)構(gòu)的軟件開發(fā)中,特別是在越大型的分布式應(yīng)用中體現(xiàn)的越明顯,后端的處理往往會因為出現(xiàn)較多的時間消耗而引起延遲,這種延遲有可能過長而最終使用戶認為是自己的操作錯誤,導(dǎo)致他們重新提交請求,由于任務(wù)的重復(fù)提交,服務(wù)器資源大部分被占用,情節(jié)嚴重可能出現(xiàn)類似死機現(xiàn)象。

          預(yù)期達到目標:
          ?? ?1、當用戶進行的是Refresh/Reload/Back/Forward操作、以及先Back再Submit操作時,僅僅是reloading先前的結(jié)果頁。
          ?? ?2、當用戶重復(fù)提交同一個任務(wù)操作時,后臺服務(wù)接收并處理第一次提交的任務(wù),后面提交不起作用(不轉(zhuǎn)向也不提示)。
          ?? ?3、該功能具有公用性。

          基本形成思路:
          ?? ?1、在basic filter中實現(xiàn)公用性
          ?? ??? ?if(true){//問題1:如何確定是否為重復(fù)提交
          ?? ??? ??? ?...
          ?? ??? ??? ?chain.doFilter(request,response);
          ?? ??? ?}else{
          ?? ??? ??? ?//問題2:如何實現(xiàn)不轉(zhuǎn)向、不提示也不顯示空白頁
          ?? ??? ?}
          ?? ?
          ?? ?2、網(wǎng)上資料概括
          ?? ??? ?a、提交表單后按鈕變灰/隱藏提交按鈕
          ?? ??? ?b、在js里設(shè)置全局變量,提交后修改該變量的值,依據(jù)變量的值判斷是否重復(fù)提交
          ??????? var flag=true;
          ??????? function checkForm(){
          ??????????? if (flag==false){
          ??????????????? return;
          ??????????? }
          ??????????? flag=false;
          ??????????? document.form1.submit();???????????????????? ?
          ??????? }
          ?? ??? ?c、struts (webwork沒有找到這個資料)
          ??????? 驗證事務(wù)控制令牌,<html:form >會自動根據(jù)session中標識生成一個隱含input代表令牌,防止兩次提交
          ??????? 在action中:????????????????????? ?
          ??????? //<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae">????????????????????? ?
          ??????? if (!isTokenValid(request))
          ??????????? errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("error.transaction.token"));
          ??????? resetToken(request); //刪除session中的令牌
          ??????? action有這樣的一個方法生成令牌華
          ??????? protected String generateToken(HttpServletRequest request) {
          ??????????? HttpSession session = request.getSession();
          ??????????? try {
          ??????????????? byte id[] = session.getId().getBytes();
          ??????????????? byte now[] = new Long(System.currentTimeMillis()).toString().getBytes();
          ??????????????? MessageDigest md = MessageDigest.getInstance("MD5");
          ??????????????? md.update(id);
          ??????????????? md.update(now);
          ??????????????? return (toHex(md.digest()));
          ??????????? } catch (IllegalStateException e) {
          ??????????????? return (null);
          ??????????? } catch (NoSuchAlgorithmException e) {
          ??????????????? return (null);
          ??????????? }
          ??????? } ?
          ?????????????????? ?
          ??? ??? d、用戶使用瀏覽器時,可以經(jīng)常使用向后的按鈕,因此就有可能重復(fù)提交一個他們已經(jīng)提交過的form,這樣就會帶來一個重復(fù)事務(wù)處理的問題。同樣,一個用戶也可能在接收到一個確認的頁面之前按下停止的按鈕,接著再次提交同一個form。對于這些情況,我們都想跟蹤并且禁止這些重復(fù)的提交,我們可以使用一個控制servlet來提供一個控制點,以解決這個問題。
          ??????? 同步記號(Synchronizer (or Dvu) Token)
          ??????? 這個策略是為了解決重復(fù)的form提交問題。一個同步的記號被設(shè)置在一個用戶的Session中,并且包含在返回到客戶的每一個form中。當form 被提交時,form中的同步標記就和Session中的同步標記作對比。在form首次提交的時候,這兩個標記應(yīng)該是一樣的。如果標記不一樣,那么該 form就會禁止提交,一個錯誤就會返回給用戶。在用戶提交一個form時,如果按下瀏覽器中的后退按鈕并嘗試重新提交同一個form時,標記就會出現(xiàn)不匹配的現(xiàn)象。
          ??????? 另一方面,如果兩個標記值匹配,那么我們就可以確信整個流程是正確的。在這種情況下,Session中的標記值就會被修改為一個新的值,同時允許提交該form。
          ??????? 你也可以使用這個策略來控制對某些頁面的直接訪問,就好象上面資源保護中描述的一樣。例如,假設(shè)一個用戶將某個應(yīng)用的頁面A收藏到收藏夾中,而頁面A只允許通過頁面B和C訪問。當用戶直接通過收藏夾來訪問頁面A,這時頁面的訪問順序就是不正確的,這樣同步標記將處在一個不同步的狀態(tài),或者它根本就不存在。不論怎樣,訪問都被禁止了。
          ?? ?
          ??? ??? e、做一個hidden框,名字自己定,提交后得到這個值放入session,提交前判斷session是否為空。
          ??? ??? f、另Struts提供利用Token防止重復(fù)提交的方法:
          ??????? 用戶請求錄入頁面,這個與服務(wù)器建立的一次連接過程中,在服務(wù)器端①【生成一個session標識,同時返回到客戶端一個與此匹配的hidden域】。用戶提交了此頁面,服務(wù)器端首先②【判斷此hidden域與session標識是否匹配】,若不匹配,終止保存操作,提示同一表單不能提交兩次,同時①【新建一個session標識和hidden域】,返回錄入頁面;若匹配,執(zhí)行插入保存操作,同時③【清空(重置reset)session標識】。
          ??? ??? Struts正在基于這樣的思路在org.apache.struts.action.Action類中提供了內(nèi)置支持方法:
          ??? ??? java代碼:
          ?? ??? ??? ??? ?
          ??? ??? ??? protected void saveToken(HttpServletRequest request) 配合標簽對應(yīng)于①
          ??? ??? ??? protected boolean isTokenValid(HttpServletRequest request) 對應(yīng)于②
          ??? ??? ??? protected void resetToken(HttpServletRequest request) 對應(yīng)于③
          ?? ??? ??? ??? ?
          ??? ??? 這樣我們在寫程序的時候,結(jié)合Struts的html標簽,只要
          ??? ??? ??? 1.在forward到insert.jsp頁面前加一個action執(zhí)行saveToken(request)操作,或干脆在insert.jsp中寫
          ??? ??? ??? 2.保存前加個判斷操作isTokenValid(request)
          ??? ??? ??? 3.若isTokenValid(request)返回false,執(zhí)行saveToken(request)操作,返回錯誤提示頁面;true則執(zhí)行resetToken(request)操作,然后進行實際的保存操作

          解決方案:
          ?? 1、后臺公共類中實現(xiàn)前臺的Form中自動生成兩個hidden文本功能,一個是作page是否重復(fù)提交判斷,并由系統(tǒng)自動附上關(guān)鍵值(如struts采用的方案);另一個作為button是否重復(fù)提交判斷(struts中好像沒有)。由后臺公共類實現(xiàn)界面兩個hidden text自動生成的好處在于公用性。
          ?? 2、在basic filter中根據(jù)兩個hidden text值判斷是否為重復(fù)提交。
          ?? 3、javascript中作一個公共方法,實現(xiàn)功能:如果需要判斷是否重復(fù)提交,就給第二個hidden text附上關(guān)鍵值,并使該功能不可用。

          posted on 2006-06-28 15:51 周游世界 閱讀(1368) 評論(0)  編輯  收藏 所屬分類: B/S設(shè)計

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 边坝县| 寿阳县| 鸡东县| 介休市| 江源县| 嘉黎县| 化州市| 巴里| 进贤县| 安龙县| 太原市| 监利县| 石首市| 北碚区| 萨嘎县| 台中市| 谢通门县| 通辽市| 渭南市| 阆中市| 泰和县| 新宾| 谢通门县| 忻城县| 绥滨县| 伊通| 铜陵市| 彭山县| 三门县| 沙田区| 金门县| 青海省| 平阳县| 临沂市| 荣昌县| 谢通门县| 报价| 盘锦市| 光山县| 洪江市| 尼勒克县|