这种问题出现的原因或者说应用场景大致如下:
- 网络延迟,服务器未能及时做出响应,导致用户不断重复点击提交按钮
- 用户双击有意识的双击或者多次点击提交按钮
- F5刷新页面
- 点击浏览器后退按钮
解决方案主要分为客户端(浏览器)和服务端以及数据库。
js禁止按钮点击
这种方式是一种比较简单也比较常用的方法。当用户提交完表单后,用javascript禁用提交按钮让按钮不可点击。也就是设置disabled属性为disabled或者true即可。按钮倒计时
页面上表单提交后,将按钮置灰不可点击后加入倒计时,比如5秒或者10秒后按钮恢复点击状态才能再次提交。这种方式也可以避免大量请求,减轻服务端访问的压力。验证码
页面上添加验证码,不管验证输入正确与否,提交后均刷新验证码。ajax加锁
采用ajax方式提交表单时,设置一个布尔变量(true/false),当然其他类型变量也可以。初始时为true可以提交,在前端向服务器发出请求后,服务端响应结果没有回来之前将该值置为false,正常响应时再置为true。提交后重定向到一个提交成功的页面
表单提交后跳转到另外一个成功页面。这样可以避免用户按F5导致的重复提交,浏览器也不会出现表单重复提交的警告,以及消除按浏览器前进和后退按导致的同样问题。服务端生成一个唯一的token
首先在服务端生成一个token保证唯一性,然后将这个token保存在session或者redis等缓存中。与此同时将token放到页面的隐藏input中,发给浏览器。用户在页面上提交时带着这个token一块提交到服务端,服务端通过比对token的值。如果相等代表首次提交,此时将session或者缓存中保存的token值remove掉,反之则认为重复提交,服务端不予处理。cookie记录表单提交的状态
使用Cookie记录表单提交的状态,根据其状态可以检查是否已经提交过表单。跟上一种类似,服务端生成token存入Cookie,表单提交时将Cookie中token和服务端token比对数据库添加唯一索引约束
向数据库字段添加一个唯一索引。如果表单重复提交,那么数据库插入重复记录时,唯一约束能有效避免重复入库。这样控制的话,日志会出现Your program attempts to store duplicate values in a database column that is constrained by a unique index的报错信息,看着有点不爽。