读书人

解决struts1.x表单重复提交有关问题

发布时间: 2012-06-26 10:04:13 作者: rapoo

解决struts1.x表单重复提交问题

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

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

如下例子:

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多了一个隐藏域: <div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="d7484f95247cf242a6f35107a1c7ac25"></div>此时生成了一个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方法中,判断令牌。

读书人网 >Web前端

热点推荐