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

一、手机端应用和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域中存储的标识号。
  在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

  1. 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
  2. 当前用户的Session中不存在Token(令牌)
  3. 用户提交的表单数据中没有Token(令牌)

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表单里 加一个隐藏文本框

185922_ebVz_2489417.png

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

185945_zicN_2489417.png

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

190107_ChF7_2489417.png

OK  

转载于:https://my.oschina.net/u/2489417/blog/779997

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值