作为程序员应该不断规范自己所写的代码,而不是在项目发布后不断修改代码,所以养成良好的编码习惯非常重要,比如用到数组时要考虑数组越界、发送请求考虑参数为空的情况。最近一个项目遇到还没完成跳转而用户重复点击提交导致数据库插入多条重复的数据,特地百度了下解决方法,下面总结下,主要分前台后台两种。
一 js防止表单重复提交
举两个方法
1、
var isCommitted = false;//表单是否已经提交标识,默认为false function dosubmit(){ if(isCommitted==false){ isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true return true;//返回true让表单正常提交 }else{ return false;//返回false那么表单将不提交 } }
2、
$("subBtn").attr("disabled",true); // 设置button不可点击
$("subBtn").attr("disabled",false); // 设置button可点击
以上方法对于 表单提交后用户点击【刷新】按钮导致表单重复提交和用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交无效!
主要利用session实现
具体的做法:在服务器端生成一个唯一的Token(令牌),同时在Session中保存这个Token。数据提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。这样重复提交的数据就不能提交了。
生成token类
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;
public class SubmitToken {
/*
*单例设计模式(保证类的对象在内存中只有一个)
*1、把类的构造函数私有
*2、自己创建一个类的对象
*3、对外提供一个公共的方法,返回类的对象
*/
private SubmitToken(){}
private static final SubmitToken instance = new SubmitToken();
/**
* 返回类的对象
* @return
*/
public static SubmitToken getInstance(){
return instance;
}
/**
* 生成Token
* Token
* @return
*/
public String makeToken(){ //checkException
String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
//数据指纹 128位长 16个字节 md5
try {
MessageDigest md = MessageDigest.getInstance("md5");
byte md5[] = md.digest(token.getBytes());
//base64编码--任意二进制编码明文字符 adfsdfsdfsf
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
测试及判断是否重复提交
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController("stokenController")
@RequestMapping("/token")
public class SubmitTokenCt extends AppBaseController {
@RequestMapping(value = "/subInfo", method = RequestMethod.GET)
public String member(HttpServletRequest request) {
Map<String, Object> map = new HashMap<String, Object>();
if (isRepeatSubmit(request)) {
map.put("msg", "请不要重复提交");
System.out.println("请不要重复提交");
return convert(map, request);
}
request.getSession().removeAttribute("ser_token");// 移除session中的token
System.out.println("提交了!!!!!!!!!!!!");
map.put("msg", "提交了!!!!!!!!!!!!");
return convert(map, request);
}
private boolean isRepeatSubmit(HttpServletRequest request) {
String cli_token = request.getParameter("cli_token");
if (StringUtils.isBlank(cli_token)) { //发过来的数据不带token,不做数据提交
return true;
}
String ser_token = (String) request.getSession().getAttribute("ser_token");
if (StringUtils.isBlank(ser_token)) { //未生成token或者数据已提交token被清除,不再重复提交数据
return true;
}
if (!cli_token.equals(ser_token)) { //发过来的token不同于存在session中的token,数据非法,不做数据提交
return true;
}
return false;
}
}
前端代码
<%
String token = SubmitToken.getInstance().makeToken();
request.getSession().setAttribute("ser_token", token);
%>
<h2><a href="/token/subInfo.jhtml?cli_token=<%=token %>&encrypt=<%= JiaUtils.jiaCrypto("123")%>&beforeEn=123">点击我!!!</a></h2>
<button οnclick="ha()" id="subBtn">提交</button>
<input value="123">
<script>
function ha(){
//$("#subBtn").attr('disabled',true);
$.ajax({
url :"/token/subInfo.jhtml",
type : "GET",
data : {
cli_token: '<%=token%>' || ''
},
dataType : "json",
success : function(data) {
//alert(data.msg);
//$("#subBtn").attr('disabled',false);
},
error : function(e) {
alert(e);
}
});
}
</script>
大家还有什么方法欢迎提出来,一起学习下