表单重复提交问题解决

重复提交:用户在点击提交后,后台程序还未处理完成,用户不知道,等得不耐烦了,又不断的点击提交,导致后台多次操作重复提交的数据,导致数据错误。所以怎样解决这样的问题呢?

解决的途径有两种:

1.前端控制

2.后台session判断

前端控制有两种方法,一个是提交后通过该将提交按钮置灰(这种体验极不好不推荐),一个是通过js控制只提交一次。

下面我们来看看通过js控制只提交一次的方式:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8">
<title>Form Page</title>
</head>
<body>
<form action="SubmitServlet" method="post" onsubmit = "return isFirstSumbmit()">
<input type = "text" name = "userName" value=""/>
<input type = "submit" value="提交">
</form>
<script type="text/javascript">
   //提交标志 true 为已提交,false为未提交
   var subFlag = false;
   function isFirstSumbmit(){
       if(!subFlag){
          subFlag = true;
          return true;
       } else {
         return false;
       }
   }
</script>
</body>
</html>

这种前端控制的方式 缺点是我提交成功过后,点浏览器的返回上一步(没有走后台的servlet),点击提交的话,数据还是会重复提交。

下面来看后端session的方式:

    进入表单页面时服务端生成token设置在前端的隐藏域中,每次提交的时候比较前端提交的token是否与服务端的一致,如果一致表明没有重复提交。保存数据成功后将服务端的token置空。如果不一致表示重复提交了(或者是前端伪造了token)。

form表单页面:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8">
<title>Form Page</title>
</head>
<body>
<form action="SubmitServlet" method="post">
<input type = "hidden" name="token" value="${token}"/> 
<input type = "text" name = "userName" value=""/>
<input type = "submit" value="提交">
</form>
</body>
</html>

进入form页面的servlet:

package com.session;

import java.io.IOException;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
// 进入到 form.jsp 的servlet 
public class ToFormPageServlet extends HttpServlet{

	public String getToken() {
		return UUID.randomUUID().toString();
	}
	@Override
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 随机生成token
		String tokenValue = getToken();
		HttpSession session = req.getSession();
		// token 放入session中
		session.setAttribute("token", tokenValue);
		System.out.println("生成token成功,token值为:"+ tokenValue);
		req.getRequestDispatcher("form.jsp").forward(req, resp);
	}
}

表单提交的servlet:

package com.session;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SubmitServlet extends HttpServlet{

	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse resp){
		resp.setContentType("text/html;charset=utf-8");
	
		if(!isFirstSubmit(req)) {
			try {
				resp.getWriter().write("表单重复提交!");
			} catch (IOException e) {
				e.printStackTrace();
			}
			return ;
		}
		
		try {
			Thread.sleep(3000);
			if(isFirstSubmit(req)){
				System.out.println("数据入库"+req.getParameter("userName"));
			}
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		try {
			resp.getWriter().write("数据保存成功!");
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 清除token
		req.getSession().removeAttribute("token");
	}
	
	/**
	 * 判断是否重复提交
	 * @param req
	 * @return
	 */
	public boolean isFirstSubmit(HttpServletRequest req) {
		// 获取表单提交的token
		String token = req.getParameter("token");
		// 去拿session里的token
		String servicToken = (String)req.getSession().getAttribute("token");
		// servicToken 为空 重复提交
		if(servicToken == null) {
			return false;
		}
		// 表单提交的token 与服务端的不一致 (防止伪造token)
		if(!servicToken.equals(token)) {
			return false;
		}
		return true;
	}
}

猜你喜欢

转载自blog.csdn.net/sinat_22808389/article/details/94557550