用户重复提交的三种解决方案

来源:互联网 发布:lua nginx module下载 编辑:程序博客网 时间:2024/05/24 06:46

用户重复提交的三种解决方案:
1.提交按钮首次提交之后消失或屏蔽,不做赘述
2.struts的同步令牌机制
首次了解这种解决方案,感觉挺好的,但随着深入,发现该方案并无实际的操作性....但思想很好,希望能给大家一些启发
原理:
1.首先通过saveToken()方法产生一个当前令牌,并通过<html:form>标签隐藏在页面中
2.提交到action时通过isTokenValid()检查用户令牌是否合法:
 2.1 如果合法,则执行业务逻辑,并通过resetToken()删除session范围内的令牌值
 2.2 如果不合法,跳转错误提示页面

本人测试情况如下:
2个action类和3个jsp类
action1的excute方法只有一句话:saveToken(request);然后跳转到operator.jsp页面,此时源码已经产生令牌
operator.jsp提交到action2中,action2的excute方法:
if(isTokenValid(request)){
 resetToken(request);//清空当前令牌
 System.out.println("开始执行业务方法了..");
 return mapping.findForward("ok");
}else{
 return mapping.findForward("error");
}
很明显的是,对于比较大的项目,肯定不会因为客户多点击一次按钮而跳转页面,专门提示...
当然对于很小的项目,或者朋友有意使用这种方案,本人则推荐进一步优化,把判断令牌这步放在
requestProcessor中来判断,比如processRoles()方法,本人优化如下:
public class Test extends RequestProcessor{
 private static TokenProcessor token = TokenProcessor.getInstance();
 protected boolean processRoles(HttpServletRequest request, HttpServletResponse response,ActionMapping mapping){
  //add,vali,no
  String tokenFlag=request.getParameter("tokenFlag");
  if(!tokenFlag.equals("no")){
   if(tokenFlag.equals("add")){
    saveToken(request);
   }else if(tokenFlag.equals("vali")){
    if(isTokenValid(request)){
     resetToken(request);
    }else{
     try {
      response.sendRedirect("./jsp/error.jsp");
      return false;
     } catch (Exception e) {e.printStackTrace();}
    }
   }
  }
  return true;
 }
 protected void saveToken(HttpServletRequest request)
 {
  token.saveToken(request);
 }
 protected boolean isTokenValid(HttpServletRequest request)
 {
  return token.isTokenValid(request, false);
 }
 protected void resetToken(HttpServletRequest request)
 {
  token.resetToken(request);
 }
}
因为Test继承RequestProcessor,故没有saveToken(),isTokenValid(),resetToken()方法,查看org.apache.struts.action.Action源码
讲三个方法拷贝过来...
因为该方法在执行任意action之前都会执行,故加以区分(add:添加令牌,vali:校验令牌,no:不需校验)
这样在首页面提交action1时要加参数tokenFlag=add,从而跳转到operator.jsp时,已经产生令牌,接着提交action2,
则会判断令牌,并加以处理...

综上,这种方案的思想不错,但实际运用,我推荐下面的第3种方案:
3.用户重复提交按钮,但并未真正进入action
原理很简单:
在页面js中声明全局变量  var submited=false;然后在提交方法的第一句判断submited的值,如为true,则return;
当然需要在提交方法的倒数第二句设置submited=true;
这种方法简单实用,不会有第1方案的美观问题,也不会有第2种的小题大作..

后话:
第2种方案的思想很不错的,在非struts项目的也可使用..同时,我们看到requestProcessor类的存在,真的很好...