解决表单重复提交的问题

来源:互联网 发布:淘宝网显示不了图片 编辑:程序博客网 时间:2024/05/22 12:27

现象描述

最近在开发的时候,遇见这样的问题,当我们在网络状况不太好的情况、或者一个业务的后台业务逻辑执行时间较长的时候,用户可能会点击多次提交或刷新多次页面,导致表单数据被提交了多次,导致了可能出现莫名其妙的问题,解决这个问题,我们可以使用session加token的方式进行解决。

方案

JSP代码:

<%@ page import="java.util.UUID" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><%@ page contentType="text/html;charset=UTF-8" %><html xmlns="http://www.w3.org/1999/xhtml"><head><title>test jsp</title></head><body><%        String token = UUID.randomUUID().toString().replaceAll("-","");        session.setAttribute("token",token);%><form id="form1" method="post" action="/user/doSomething.do">    username : <input type="text" id="username" value=""/>    password : <input type="text" id="password" value=""/>    <input type="hidden" name="formtoken" value="<%=token%>" >    <input type="submit" value="submit"/></form></body></html>

Controller层:

@Controller@RequestMapping(value="user")public class UserController {    @RequestMapping(value="doSomething.do")    public String doSometing(String username, String password, HttpServletRequest request, RedirectAttributes attr) {        String formToken = request.getParameter("formtoken");        HttpSession session = request.getSession();        String token = (String)session.getAttribute("token");        if (formToken.equals(token)) {            session.removeAttribute("token");        } else {            attr.addFlashAttribute("msg", "请不要重复提交!");            return "redirect:error";        }    }}

如果有多个Controller的方法都需要进行校验,可以写一个单独的校验方法,使用@ModelAttribute注解,这样让它在所有方法执行之前执行,校验是否表单重复提交了

@Controller@RequestMapping(value="user")public class UserController {    @ModelAttribute    public void checkForm(HttpServletRequest request, Model model) {            String formToken = request.getParameter("formtoken");            HttpSession session = request.getSession();            String token = (String)session.getAttribute("token");            if (formToken.equals(token)) {                session.removeAttribute("token");                model.addAttribute("checkResult", "success");            } else {                model.addAttribute("checkResult", "fail");        }    }       @RequestMapping(value="doSomething.do")    public String doSometing(@ModelAttribute String checkResult, String username, String password, RedirectAttributes attr) {        if (checkResult != null && checkResult.equals("success"))         {            doSomething(username, password);            } else {            attr.addFlashAttribute("msg","请不要重复提交");            return "redirect:error";        }    }}

原理

当多次提交的时候,session中的token已经更新,但是form中的token没有变化,因此可以用此进行校验。