防止訂單重復提交


電商項目中,用戶可能經常要下訂單。這時有一點需要我們考慮到:防止訂單重復提交。

也就是說,我下單成功后,刷新頁面,再次生成訂單就會產生誤會了。用戶明明下了一次單,你卻給人家發兩次貨,給人家收兩次錢。


那么我們分析一下造成訂單重復提交的原因有哪些?

一是轉發引起的。

我們知道頁面跳轉有兩種方式:轉發和重定向。所謂轉發是在服務器端進行跳轉,對用戶時透明的,這時,瀏覽器中的地址是不會改變的。所以,如果此時刷新頁面,會再次對服務器請求一次,造成多次下單;

而重定向,是在客戶端發生跳轉,跳轉時瀏覽器中的地址會發生改變。也就是說,我下單成功后,會馬上重定向到一個新頁面,瀏覽器地址欄改變,這是刷新,只會請求顯示的地址,而不會請求上一次的地址。


*注:重定向如果需要傳遞參數,可以采用下面方式

?
1
2
3
     <result name= "success" type= "redirect" >/test/addSuccess.action?productId=${productId}</result>
</action>



二是服務器響應慢引起的。

當用戶點擊下訂單后,由於服務器反應時間過長沒能及時看到響應信息,或者出於其它目的,多次點擊“提 交”按鈕,從而導致在服務器端接收到兩條或多條相同的信息。如果信息需要存儲到后台數據庫中,如此以來就會產生數據庫操作異常提示信息,以至於給用戶帶來 錯誤信息提示,從而給用戶的使用帶來不便。


如何解決?

以下思路,可以當個參考:

1、下單成功后,重定向到其他頁面

這種方式,只能解決刷新時,生成訂單的可能,但是不能防止多次點擊的情況。

2、利用struts2的token攔截器


原理:

Struts 2已經內置了能夠防止用戶重復提交同一個HTML表單的功能。它的工作原理:讓服務器生成一個唯一標記,並在服務器和表單里各保存一份這個標記的副本。此 后,在用戶提交表單的時候,表單里的標記將隨着其他請求參數一起發送到服務器,服務器將對他收到的標記和它留存的標記進行比較。如果兩者匹配,這次提交的 表單被認為是有效的,服務器將對之做出必要的處理並重新設置一個新標記。隨后,提交相同的表單就會失敗,因為服務器上的標記已經重置。

Struts 2標簽中的token標簽,可以用來生成一個獨一無二的標記。這個標記必須嵌套在form標簽中使用,它會在表單里插入一個隱藏字段並把標記保存到 HttpSession對象里。toke標簽必須與Token或Token Session攔截器配合使用,兩個攔截器都能對token標簽進行處理。Token攔截器遇到重復提交表單的情況,會返回一 個"invalid.token"結果並加上一個動作級別的錯誤。Token Session攔截器擴展了Token攔截器並提供了一種更復雜的服務,它采取的做法與Token攔截器不同,它只是阻斷了后續的提交,這樣用戶不提交多 少次,就好像只是提交了一次。


附Struts2的token攔截器demo一個:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
     pageEncoding= "UTF-8" %>
        <%
     String path = request.getContextPath();
     String basePath = request.getScheme()+ "://" +request.getServerName()+ ":" +request.getServerPort
 
()+path+ "/" ;
%>
<% @taglib uri= "/struts-tags" prefix= "s" %>
 
 
     
<meta charset= "utf-8"
 
 
 
     <s:form id= "payFrm" action= "" >
         <s:hidden type= "hidden" name= "bankCardsId" id= "bankCardsId" value= "'0'/" >
         <s:hidden type= "hidden" name= "productId" value= "%{#request.productId}" >
         <s:token></s:token>
     </s:hidden></s:hidden></s:form>
     <span class = "sureBuy" >確認訂單</span>
 
<script type= "text/javascript" src= "<%=basePath %>weixin/js/fx.js" ></script>
  <script type= "text/javascript" src= "<%=basePath %>weixin/js/fx_methods.js" ></script>
<script>
$(function(){
$( ".sureBuy" ).click(function(){
     var form = document.getElementById( "payFrm" );           
         form.action = "<%=path%>" +/test/sureOrder.action;
         form.method = "post" ;
         form.submit();
});
     
</script>


struts2配置文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< package name= "mallOrderAction" extends = "json-default" namespace= "/test" >
         
             <interceptor-ref name= "defaultStack" >
             <interceptor-ref name= "token" >
             <result name= "invalid.token" type= "redirect" >/test/payRepeat.action</result>
             <result name= "error" >/test/payError.jsp</result>
             <result name= "success" type= "redirect" >/test/orderSuccess.action?productId=${productId}</result>
         </interceptor-ref></interceptor-ref></action>
         
             <result name= "success" >/test/payRepeat.jsp</result>
         </action>
         
             <result name= "success" >/test/orderSuccess.jsp</result>
         </action>
 
</ package >


action類文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class orderAction extends ActionSupport{
     /**
      * @MethodName  : sureOrder
      * @Description : 添加訂單
      * @return
      * @throws Exception
      */
     public String sureOrder() throws Exception{
         
         //………下單的各種步驟…………………
         return SUCCESS;
         
     }
     
     /**
      * @MethodName  : payRepeat
      * @Description : 重復提交
      * @return
      */
     public String payRepeat(){
         return SUCCESS;
     }
     
     /**
      * @MethodName  : addSuccess
      * @Description : 下單成功
      * @return
      */
     public String addSuccess(){
         HttpServletRequest request = ServletActionContext.getRequest();
         Product product = product.getproductId(productId);
         request.setAttribute( "product" , product);
         return SUCCESS;
     }
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM