解决struts后退和刷新页面重复提交的方案

来源:互联网 发布:js list取指定元素 编辑:程序博客网 时间:2024/05/24 01:41

        最近做了一个struts的小工程,由于是经验太少,遇到了这样的问题:struts执行完跳转后,它的动作仍然是停留在上一步,如:新增后我把页面转到列表页面,我刷新一下页面,就又新增了上一条记录;由于本人是菜鸟,也费了不少劲,所以写在这供同样是菜鸟的人参考,解决方案如下:

        一、在跳转到新增页面的Action方法中,加入一条saveToken(request)语句,下面是实例:

         public ActionForward goAdd(ActionMapping mapping, ActionForm form,
               HttpServletRequest request, HttpServletResponse response) {
               HttpSession session=request.getSession();
               saveToken(request); //获取一个标记,置于session中
               return mapping.findForward("goUrlAdd");
         }

    二、新增成功后的Action方法,跳到list页面,加入验证:

         public ActionForward addAdvice(ActionMapping mapping, ActionForm form,
               HttpServletRequest request, HttpServletResponse response) {
              AdviceForm adviceForm = (AdviceForm) form;
              ns = new AdviceService();

              if(isTokenValid(request, true)) {
                   boolean flag = ns.addAdvice(adviceForm);
                   if (flag == true) {

                        request.setAttribute("result", Constant.sucResult("新增信息成功!"));
                        return search(mapping,form,request,response);
                   } else {

                        request.setAttribute("result", Constant.sucResult("新增信息失败!"));
                        return search(mapping,form,request,response);
                   } 
                  } else {
                       return search(mapping,form,request,response);
                  }
         }

        红色标识就是为了解决这个问题而加的。

        方案原理是:利用struts的同步令牌机制  
  利用同步令牌(Token)机制来解决Web应用中重复提交的问题,Struts也给出了一个参考实现。  
  服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。 
  if (isTokenValid(request, true)) {
   // your code here
   return mapping.findForward("success");
  } else {
   saveToken(request);
   return mapping.findForward("submitagain");
  } 
  Struts根据用户会话ID和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考TokenProcessor类中的generateToken()方法。  
  1. //验证事务控制令牌,会自动根据session中标识生成一个隐含input代表令牌,防止两次提交
  2. 在action中:  
  // value="6aa35341f25184fd996c4c918255c3ae">
   if (!isTokenValid(request))
errors.add(ActionErrors.GLOBAL_ERROR,
   new ActionError("error.transaction.token"));
   resetToken(request); //删除session中的令牌  
  3. action有这样的一个方法生成令牌  
   protected String generateToken(HttpServletRequest request) {  
   HttpSession session = request.getSession();
   try {
   byte id[] = session.getId().getBytes();
   byte now[] =
   new Long(System.currentTimeMillis()).toString().getBytes();
   MessageDigest md = MessageDigest.getInstance("MD5");
   md.update(id);
   md.update(now);
   return (toHex(md.digest()));
   } catch (IllegalStateException e) {
   return (null);
   } catch (NoSuchAlgorithmException e) {
   return (null);
   }
   }

 

原创粉丝点击