防止订单重复提交

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

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

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

一是转发引起的。

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

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

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

<action name="test" class="testAction" method="test">
	<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一个:

<%@ 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" %>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</html>
</head>
<body>
	<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:form>
	<span class="sureBuy">确认订单</span>
</body>
<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配置文件:

<package name="mallOrderAction" extends="json-default" namespace="/test">
		<action name="sureOrder" class="mallOrderAction" method="sureOrder">
			<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>
		</action>
		<action name="payRepeat" class="mallOrderAction" method="payRepeat">
			<result name="success">/test/payRepeat.jsp</result>
		</action>
		<action name="addSuccess" class="mallOrderAction" method="addSuccess">
			<result name="success">/test/orderSuccess.jsp</result>
		</action>

</package>

action类文件:

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;
	}
}
时间: 2024-08-12 09:51:29

防止订单重复提交的相关文章

ASP.NET Web Form和MVC中防止F5刷新引起的重复提交问题

转载  http://www.cnblogs.com/hiteddy/archive/2012/03/29/Prevent_Resubmit_When_Refresh_Reload_In_ASP_NET_Web_Form_MVC.html 什么是刷新/重新载入 IE中的刷新(Refresh),在FF和Chrome中称为重新载入(Reload),与正常进入页面的区别在于以下两点: 1. 缓存控制 如果文件(比如图片)在本地缓存中已经存在,正常进入页面会不访问服务器而直接从本地加载.而对于刷新操作,

MVC_防止HttpPost重复提交

重复提交的场景很常见,可能是当时服务器延迟的原因,如购物车物品叠加,重复提交多个订单.常见的解决方法是提交后把Button在客户端Js禁用,或是用Js禁止后退键等.在ASP.NET MVC 3 Web Application中 如何去防止这类HTTP-Post的重复提交呢? 我们可以借助Session,放置一个Token在View/Page上,然后在Server端去验证是不是同一个Token来判断此次Http-Post是否有效.看下面的代码:  首先定义一个接口,便于扩展. public int

由表单重复提交引发的幂等性思考

1. 什么时候需要实现幂等性接口? 在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同.既然是这样我们的查询和删除不就是多次执行的结果和一次执行的相同吗.是的,查询和删除拥有天然的幂等性,当然删除这个第一次执行和后面执行的返回值可能会有所不同,但是最终的效果是一致的.所以需要我们额外实现的幂等性接口主要是新增和更新操作. 2.实现幂等的解决方案 ①  token 机制防止表单重复提交 redis 预存一个 token 并分发到客户端.当客户端提交请求时,携带这个 tok

php防止用户重复提交表单

我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦. 效果图: 那么如何规避这中重复提交表单的现象出现呢?我们可以从很多方面入手: 首先从前端做限制.前端JavaScript在按钮被点击一次后禁用,即disabled,这个方法简单的防止了多次点击提交按钮,但是缺点是如果用户禁用了javascript脚本则失效. 第二,我们可以在提交后做redirect页面重定向,

表单重复提交问题

一.常见的重复提交问题  a>点击提交按钮两次.  b>点击刷新按钮.  c>使用浏览器后退按钮重复之前的操作,导致重复提交表单.  d>使用浏览器历史记录重复提交表单.  e>浏览器重复的HTTP请求. 二.防止表单重复提交原理 提交表单的时候提交一份随机的字符串或随机数字等等,再把这个随机的数据存到request里面,然后把表单数据提交,在后台验证的时候判断提交的这两份额外的数据是否一致,如果一致,则把其中一份删除掉,这么做的目的是防止再次提交,继续进行操作,如果不一致,

JavaWeb 之 重复提交表单和验证码相关的问题!

下面我们首先来说一下表单的重复提交问题,我们知道在真实的网络环境中可能受网速带宽的原因会造成页面中表单在提交的过程中出现网络的延迟等问题,从而造成多次提交的问题!下面我们就具体来分析一下造成表单提交的一些常见问题. 下面我们就来列举一下重复提交的情况: ① .当表单提交数据到一个 Servlet 中,然后 Servlet再通过请求转发到成功页面,但是此时的地址栏中的地址是到 Servlet映射中的地址,并没有跳转到成功页面相关的JSP页面中,此时刷新页面会造成再一次提交表单. ② .当在表单页面

防止表单重复提交

客户端防止表单重复提交: 不足之处:用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交 <script type="text/javascript"> //方式一 var iscommitted = false; function dosubmit(){ if(!iscommitted){ iscommitted = true; return true; }else{ return false; } } //方式二 function dosubmit(){ d

struts2 文件的上传下载 表单的重复提交 自定义拦截器

文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置为 post 需添加 <input type=“file”> 字段. Struts 对文件上传的支持 在 Struts 应用程序里, FileUpload 拦截器和 Jakarta Commons FileUpload 组件可以完成文件的上传. 步骤:1. 在 Jsp 页面的文件上传表单里使用

[原创]java WEB学习笔记34:Session 案例 之 解决表单重复提交

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------