解决表单重复提交
记得前几次面试的时候,3家公司问了表单重复提交的问题,我回答的都不是特别好,虽然知道是个什么流程,但是因为只知道理论,所以面试官问的细一点就懵了
这次就写了一个demo测试一下之前的想法是否准确.
1 表单重复提交大部分情况是用户点击提交时,因为服务端处理数据太慢,没能及时返回结果给用户,用户重复的点击提交按钮,这个时候就会出现重复提交,这里我用Thread.sleep增加响应延迟
2 用户提交表单成功,服务端处理完成并将结果响应给用户了.但是可能用户手滑一直f5请求刷新,这时候也会造成表单重复提交
3 用户提交表单成功,服务端处理完成并将结果响应给用户了.但是可能用户手滑一直返回提交返回提交,这时候也会造成表单重复提交
鉴于以上3种经常出现情况,都有相应的解决方案
1 js方案
提交按钮设置为不可用状态. 但是无法防止2,3种情况发生
<form action="${pageContext.request.contextPath}/fromResubmit/submit2" method="post" onsubmit="preEvent()">
用户名:<input type="text" name="username">
<input type="submit" value="提交" id="submit_id">
</form>
<script type="application/javascript">
function preEvent() {
document.getElementById("submit_id").setAttribute("disabled", "disabled");
}
</script>
2 当用户请求form页面时,在服务端生成token,并存放在当前用户session中和form页面表单的隐藏域中
当用户点击请求时必须将表单隐藏的token传入到服务端,然后进行两端token的验证,验证不同过打回去
@RequestMapping("/doForm")
public String doForm(HttpServletRequest request) {
//创建token
String token = UUID.randomUUID().toString();
//在服务端session中保存token
request.getSession().setAttribute("token", token);
System.out.println("本次生成的token:" + token);
//跳转到form页面
return "/fromResubmit/form";
}
@RequestMapping(value = "/submit", produces = "text/html;charset=UTF-8")
@ResponseBody
public String submit(HttpServletRequest request) {
//取出客户端表单中的token,如果表单中没有token则认为用户是重复提交
String clientToken = request.getParameter("token");
if (StringUtils.isEmpty(clientToken)) {
return "请不要重复提交";
}
//取出服务端当前用户session中的token,如果为空则认为用户重复提交
String serviceToken = (String) request.getSession().getAttribute("token");
if (StringUtils.isEmpty(serviceToken)) {
return "请不要重复提交";
}
//判断两个客户端和服务端我token是否相同,不相同认为用户重复提交
if (!Objects.equals(clientToken, serviceToken)) {
return "请不要重复提交";
}
//确定本次请求不是重复提交,移除session中的token
request.getSession().removeAttribute("token");
return "提交成功";
}
<form action="${pageContext.request.contextPath}/fromResubmit/submit" method="post">
<%--使用EL表达式取出存储在session中的token,并存放在表单隐藏域中--%>
<input type="hidden" name="token" value="${token}"/>
用户名:<input type="text" name="username">
<input type="submit" value="提交">
</form>
总结
有些基础的东西真的很值得深究啊,就拿这个表单重新提交 我发现我们公司的项目组没有一个有重复验证的
之前我做的那个重复回款验证的 也是根据现有的数据用redis做的锁来验证重复提交的,之后再根据状态来验证是否打回去,所以完全不适用上面的方案
如果项目是集群部署的话 可以考虑用一个中间件来替换session,这样就不会出现重复提交的尴尬了
上一篇: 将Series和DataFrame存储到mysql数据库中
下一篇: 比赛14 总结
推荐阅读
-
解决表单重复提交
-
Spring Boot学习总结(21)——SpringBoot集成Redis等缓存以注解的方式优雅实现幂等,防千万次重复提交实例代码
-
解决Tomcat重复加载Spring配置文件 博客分类: Tomcat tomcat重复加载Spring配置Initializing Spring root WebApplicationContext
-
SpringBoot Redis 解决重复提交问题
-
Unity Spine SkeletonGraphic 动画重复播放 过度残影Bug 解决方案
-
Splite3解决SVN无法提交的问题
-
struts2后台重复获取前台参数问题 博客分类: 数据交互 strutsexcel拼接参数表单提交
-
hibernate中重复显示问题的解决方法 HibernateOpenSourceSQL
-
PHP实现登陆表单提交CSRF及验证码
-
javaweb用户注销后点击浏览器返回刷新页面重复登录问题的解决方法