zoukankan      html  css  js  c++  java
  • 防止订单重复提交

    电商项目中,用户可能经常要下订单。这时有一点需要我们考虑到:防止订单重复提交。

    也就是说,我下单成功后,刷新页面,再次生成订单就会产生误会了。用户明明下了一次单,你却给人家发两次货,给人家收两次钱。


    那么我们分析一下造成订单重复提交的原因有哪些?

    一是转发引起的。

    我们知道页面跳转有两种方式:转发和重定向。所谓转发是在服务器端进行跳转,对用户时透明的,这时,浏览器中的地址是不会改变的。所以,如果此时刷新页面,会再次对服务器请求一次,造成多次下单;

    而重定向,是在客户端发生跳转,跳转时浏览器中的地址会发生改变。也就是说,我下单成功后,会马上重定向到一个新页面,浏览器地址栏改变,这是刷新,只会请求显示的地址,而不会请求上一次的地址。


    *注:重定向如果需要传递参数,可以采用下面方式

    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;
        }
    }


  • 相关阅读:
    openswitch db files
    openstack中虚拟机和其网络的联系方法 instance and network
    python操作db2和mysql ,ibm_db
    yum安装mariadb
    python 连接 db2
    db2操作 连接、备份、恢复db2
    su su
    linux 后台运行进程 fg bg ctrl+z nohup
    mysql 命令行
    IDEA-使用技巧
  • 原文地址:https://www.cnblogs.com/jpfss/p/8072484.html
Copyright © 2011-2022 走看看