解决表单重复提交

   记得前几次面试的时候,3家公司问了表单重复提交的问题,我回答的都不是特别好,虽然知道是个什么流程,但是因为只知道理论,所以面试官问的细一点就懵了

这次就写了一个demo测试一下之前的想法是否准确.

1   表单重复提交大部分情况是用户点击提交时,因为服务端处理数据太慢,没能及时返回结果给用户,用户重复的点击提交按钮,这个时候就会出现重复提交,这里我用Thread.sleep增加响应延迟

 

2  用户提交表单成功,服务端处理完成并将结果响应给用户了.但是可能用户手滑一直f5请求刷新,这时候也会造成表单重复提交

解决表单重复提交_第1张图片

 

3  用户提交表单成功,服务端处理完成并将结果响应给用户了.但是可能用户手滑一直返回提交返回提交,这时候也会造成表单重复提交

解决表单重复提交_第2张图片


鉴于以上3种经常出现情况,都有相应的解决方案

1 js方案

提交按钮设置为不可用状态.  但是无法防止2,3种情况发生

用户名:

 

解决表单重复提交_第3张图片

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 "提交成功";
    }
<%--使用EL表达式取出存储在session中的token,并存放在表单隐藏域中--%> 用户名:


总结

有些基础的东西真的很值得深究啊,就拿这个表单重新提交 我发现我们公司的项目组没有一个有重复验证的   

之前我做的那个重复回款验证的  也是根据现有的数据用redis做的锁来验证重复提交的,之后再根据状态来验证是否打回去,所以完全不适用上面的方案

如果项目是集群部署的话  可以考虑用一个中间件来替换session,这样就不会出现重复提交的尴尬了

源码在此:https://github.com/zhouminsen/web

你可能感兴趣的:(javaweb)