【小轮子】自定义标签防止表单重复提交          返回主页

重复提交的情景:

    一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,
    由于更新、删除一般都是通过id来操作(例如: updateXXXById, removeXXXById),
    所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。

1.常见防重提交的方式主要有:js方式 验证码 令牌

2.这里主要介绍第三种:

其实从原理上来说,第二种跟第三种是一样的。 都是通过生成随机数,存放于session,使得重复提交时获取到的数据与上一次发的数据不一致,从而不满足提交条件。

这里我封装了一个jar用于快速实现表单重复提交,这个功能很多框架已经实现,不过自己写的工具在个人程序中用起来还是蛮方便的。

使用方法

  1. token令牌机制,参考配置在压缩包中的meta-inf下
  2. 复制snowalker.tld到web-inf下
  3. 配置web.xml

            配置过滤器
           <filter>
            <display-name>TokenFilter</display-name>
            <filter-name>TokenFilter</filter-name>
            <filter-class>com.snowalker.token.filter.TokenFilter</filter-class>
            <init-param>
                    <param-name>dispacher</param-name>
                    <param-value>student/index.html</param-value>
            </init-param>
          </filter>
          <filter-mapping>
            <filter-name>TokenFilter</filter-name>
            <url-pattern>/login.html</url-pattern>
          </filter-mapping>
    
  4. url-pattern为想要过滤的位置,一般是表单提交的目标action;初始化参数表示重定向位置,避免重新访问action造成重复提交

        ========页面引用===========
        页面中通过在表单中添加<snowalker:token/>引用标签
        在jsp头部添加头信息
        <%@ taglib prefix="snowalker" uri="http://www.wuwenliang.net/anti-resubmit/core" %>
        =======可参照demo进行操作====
    

原理

1. tag类

    /**
     * 
     * @作者 snowalker
     * @时间 2016年10月17日
     * @描述 防止重复提交标签
     *      生成Token并写入Session及输出流中的隐藏表单域并写回页面
     *      判断页面中的Token值与session中是否相同
     *              相同则提交,并清除Session的token值
     *              不相同则为重复提交,因为此时Session中的token已经不是之前的那个值
     */

    //生成token使用UUID
    String token = UUID.randomUUID().toString();
    //将token写入Session
    PageContext pageContext = (PageContext) getJspContext();
    pageContext.getSession().setAttribute("token", token);
    //token写入隐藏表单域
    JspWriter out = pageContext.getOut();
    out.write("<input type=\"hidden\" name=\"token\" value=\"" + token + "\"/>"); 

解释: 1. 使用UUID生成唯一的标记,并设置到session 2. doTag方法中输出一个html隐藏表单域并带上该token

2.TokenFilter过滤器,用于对token进行比对

            //比对Token
            String iToken = request.getParameter("token");
            HttpSession session = request.getSession();
            String sToken = (String) session.getAttribute("token");
            //相等则提交并移除session中的token
            if (iToken != null && iToken.equals(sToken)) {
                session.removeAttribute("token");
                chain.doFilter(request, response);
            } else {
                //重定向到目标页面,配置中填写相对于更路径的逻辑路径
                response.sendRedirect(request.getContextPath() + "/" + dispacher);
            }

解释: 1. 将前台标签中的token值与session中的比对 2. 相同则进行请求的链式传递 3. 不同则直接重定向到目标的当前页面,也就是只进行一次表单提交动作

小结

总的来说,只需要引入该jar包,并在需要进行防重提交的form内部引入标签

在web.xml的过滤器配置中写入初始化参数为避开重复提交位置的目标刷新位置即可