以前作安卓或苹果手机应用开发时,好比发帖子,点发布按钮后时,咱们每每会作一些操做,好比按钮变灰,而后增长一个转圈加载的遮罩,主要是为了防止用户快速点击形成屡次提交数据。java
web开发时也会有相似的问题。增长、修改、删除这些处理业务的操做也会有形成屡次提交数据的问题。web
若是网速比较慢的状况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会觉得是本身没有提交表单,就会再点击提交按钮重复提交表单。面对这个状况,若是只是在jsp页面,加上js判断的代码浏览器
var checkSubmitFlg = false;服务器
function check(){session
if (checkSubmitFlg == true){dom
alert("重复提交");jsp
return;编码
}else{spa
checkSubmitFlg = true; .net
myform.submit();
}
}
JavaScript是能够解决这个问题的,固然还能够"用JavaScript控制Form表单只能提交一次"。只是点提交按钮后让按钮变灰相似手机端的作法。可是这种作法针对如下2,3场景确不行。
场景二表单提交后用户点击【刷新】按钮致使表单重复提交 和 场景三用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交,用户这样的操做为了解决重复提交表单的问题,咱们能够在服务端利用session去解决。
具体的作法:在服务器端生成一个惟一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。而后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一块儿提交到服务器端,而后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,若是不一致,那就是重复提交了,此时服务器端就能够不处理重复提交的表单。若是相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
在下列状况下,服务器程序将拒绝处理用户提交的表单请求:
封装了一个类TokenProcessor 代码以下
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import sun.misc.BASE64Encoder;
/**
* 类说明:令牌 防止刷新或程序打断点或快速点击 重复提交
* @author wangbx
* @date 2016年11月2日 下午2:41:34
*/
public class TokenProcessor {
private static final TokenProcessor instance = new TokenProcessor();
private TokenProcessor(){}
public static TokenProcessor getInstance(){
return instance;
}
public String generateToken(){
String token = System.currentTimeMillis()+new Random().nextInt()+"";
try{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
//base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
}catch(NoSuchAlgorithmException e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 功能描述:判断session中token是否失效 true:没有失效
* @author wangbx
* @date 2016年11月2日 下午4:04:23
* @param @param request
* @param @return
* @return boolean
*/
public synchronized boolean isTokenValid(HttpServletRequest request) {
String client_token=request.getParameter("token");
if(client_token==null)
{
return false;
}
String server_token=(String)request.getSession().getAttribute("token");
if(server_token==null)
{
return false;
}
if(!client_token.equals(server_token))
{
return false;
}
return true;
}
/**
* 功能描述:为请求新建一个token标记,并把字符值存入session中
* @author wangbx
* @date 2016年11月2日 下午4:16:41
* @param @param request
* @return void
*/
public synchronized void saveToken(HttpServletRequest request){
HttpSession session = request.getSession(true);
TokenProcessor tp=TokenProcessor.getInstance();
String token=tp.generateToken();
session.setAttribute("token", token);
}
/**
* 功能描述: 从新设置token,当页面被请求后,将session中的token属性去除
* @author wangbx
* @date 2016年11月2日 下午4:20:38
* @param @param request
* @return void
*/
public synchronized void resetToken(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(session != null){
session.removeAttribute("token");
}
}
}
针对开发人员的全部模块 须要在三处复制下代码
1、jsp界面的form表单里 加一个隐藏文本框
2、跳到发布的界面或修改界面前的方法里 要添加两行代
3、在具体提交方法加上下面代码
OK