您的位置:首页 > 其它

web开发解决页面重复提交问题

2016-11-02 00:00 225 查看

一、手机端应用和web开发类似的问题

之前做安卓或苹果手机应用开发时,比如发帖子,点发布按钮后时,我们往往会做一些操作,比如按钮变灰,然后增加一个转圈加载的遮罩,主要是为了防止用户快速点击造成多次提交数据。

web开发时也会有类似的问题。增加、修改、删除这些处理业务的操作也会有造成多次提交数据的问题。

1、场景一(多次点击按钮提交表单)

如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单。面对这个情况,如果只是在jsp页面,加上js判断的代码

var checkSubmitFlg = false;

function check(){

if (checkSubmitFlg == true){

alert("重复提交");

return;

}else{

checkSubmitFlg = true;

myform.submit();

}

}

JavaScript是可以解决这个问题的,当然还可以"用JavaScript控制Form表单只能提交一次"。只是点提交按钮后让按钮变灰类似手机端的做法。但是这种做法针对以下2,3场景确不行。

2、场景二 (点刷新) 场景三(点后退)

场景二表单提交后用户点击【刷新】按钮导致表单重复提交 和 场景三用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交,用户这样的操作为了解决重复提交表单的问题,我们可以在服务端利用session去解决。

具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
  在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

存储Session域中的[b]Token(令牌)与表单提交的Token(令牌)不同。[/b]

当前用户的Session中不存在[b]Token(令牌)。[/b]

用户提交的表单数据中没有[b]Token[b][b](令牌)[/b][/b]。[/b]

3、代码

封装了一个类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");
}
}

}

针对开发人员的所有模块 需要在三处复制下代码

一、jsp界面的form表单里 加一个隐藏文本框



二、跳到发布的界面或修改界面前的方法里 要添加两行代



三、在具体提交方法加上下面代码



OK
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: