开发者社区 问答 正文

easyui 重复提交如何解决

    js代码 
    $('#btn_add').click(function(){
        proper.dialogForm({
            title:'增加商品',
            width:350,
            height:420,
            maximized:true,
            commitURL:'<%=basePath %>allfields/allfieldsProductInfoQly/addProduct.do',
            href:'<%=basePath%>allfields/allfieldsProductInfoQly/addForm.do',
            commitSuccess:function(resp){
                $.messager.alert('系统消息',resp);
                $("#tablegrid").datagrid( "reload");
            }
        });
    });

展开
收起
小旋风柴进 2016-03-20 11:12:47 3717 分享 版权
1 条回答
写回答
取消 提交回答
  • 每次填写完表单后单击提交后,struts中action执行相关业务逻辑,通过forward对象转到某个页面。这时若刷新页面后,会再执行同样的逻辑。比如录数据到数据库,按照上面的情况,数据库中会有两条同样的数据。为了避免这种情况,有几种解决办法:

    1 :在执行业务逻辑后,返回一个Forward对象,这个forward对象的path属性应该配置一个幂等的XXX.do操作,这样可以解决,但是有可能不符合用户的要求,所以还有其他方法。

    2:重定向,在配置文件里配置redirect属性,重定向到xxx.jsp。这种情况下会丢失request范围内的参数,若xxx.jsp不要求这些参数就可以,如操作的数据保存在session范围内,就不会影响整体效果。但还是有弊端。

    3:利用struts1.x令牌能很好解决这类问题。

    必要条件:在表单内,必须使用struts的库标签如:。

    如下例子:

    LoginAction:
     package com.web.action;
     import javax.servlet.http.HttpServletRequest;
     import javax.servlet.http.HttpServletResponse;
     import org.apache.struts.action.ActionForm;
     import org.apache.struts.action.ActionForward;
     import org.apache.struts.action.ActionMapping;
     import org.apache.struts.actions.DispatchAction;
     public class LoginAction extends DispatchAction  {
        public ActionForward get(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
               throws Exception  {
           //保存令牌(保存在jsp动态生成的32位jsessionid)\
            this.saveToken(request);
            System.out.println("begin save");
            return mapping.findForward("login");
        }
        
        public ActionForward login(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
                throws Exception  {
            /**//*if(this.isTokenValid(request))
            {
                System.out.println("valid");
                this.resetToken(request);
                return mapping.findForward("ok");
            }*/
            //这个写法和上面注释部分一样效果
            if(this.isTokenValid(request,true))
             {
                System.out.println("valid");
                return mapping.findForward("ok");
            }
            else
            {
                System.out.println("invalid");
                return mapping.findForward("error");
            }
        }
    }
    struts-config.xml:
     <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
     <struts-config>
         <data-sources />
         <form-beans>
             <form-bean name="loginForm" type="com.web.form.LoginForm"></form-bean>
         </form-beans>
         <global-exceptions />
         <global-forwards />
         <action-mappings>
             <action path="/login" parameter="method" name="loginForm"
                 type="com.web.action.LoginAction">
                 <forward name="login" path="/login.jsp" />
                 <forward name="ok" path="/ok.jsp" />
                 <forward name="error" path="/error.jsp" />
             </action>
         </action-mappings>
         <message-resources parameter="" />
     </struts-config>
    index.jsp:
    <% @page contentType="text/html; charset=GBK"%>
    <% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     <c:set var="ctx" value="${pageContext.request.contextPath}" />
     <html>
       <head>
         <title>My Jsp</title>
       </head>
       <body>
       <a href="${ctx}/login.do?method=get">发言</a>
       </body>
     </html>
     
    
    login.jsp:
    <% @page contentType="text/html; charset=GBK"%>
    <% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <% @taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
     <html>
       <head>
         <title>My Jsp</title>
       </head>
       <body>
       <c:set var="ctx" value="${pageContext.request.contextPath}"/>
       <!-- 此处必须使用html标签,否则token不能用 -->
       <html:form action="login.do?method=login" method="post">
         <html:submit value="提交"></html:submit>
       </html:form>
       </body>
     </html>

    当你运行第一次的时候,会提示你"成功".
    这时我们退到login.jsp查看一下源代码:

     <html>
       <head>
         <title>My Jsp</title>
       </head>
       <body>
       
       <form name="loginForm" method="post" action="/strutsToken/login.do?method=login">
     <div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="d7484f95247cf242a6f35107a1c7ac25"></div>
         <input type="submit" value="提交">
       </form>
       </body>
     </html>

    对比一下我们写的login.jsp多了一个隐藏域:


    此时生成了一个32位的唯一的JsessionID做为值.
    与LoginAction中的get方法的saveToken(request)是一样的.
    此句的作用就是把一个jsessionid保存到request范围里.

    在我们后退重新调用:

     if(this.isTokenValid(request,true))
             {
                System.out.println("valid");
                return mapping.findForward("ok");
            }

    时,就会拿login.jsp里传过来的jsessionid和request的
    进行比较,如果一样,说明不合法.因为我们的操作都是在一个请求会话里
    操作的.说明你在重复提交.
    如果不一样,说明重新生成了一个唯一的jsessionid(新开一个浏览器),
    开启了一个新会话,重新提交,这是合法的.
    这样就防止了表单重复提交问题.
    为了防止表单重复提交,一般在设计action方法时:如录入数据,设计成两个方法,add()和insert(),在add方法中保存令牌并转到页面,在页面提交到insert方法中,判断令牌。

    2019-07-17 19:09:10
    赞同 展开评论
问答分类:
问答地址: