1. 程式人生 > >關於struts2防止表單重復提交

關於struts2防止表單重復提交

template exe exception soft con message pac ucc request

struts2防表單重復提交有兩種方式。

其一是action的重定向,跳轉時設置type為從一個action跳轉到另一個action或者另一個頁面,

使用戶提交後,所停留的位置,不是當前處理數據的Action,這樣用戶再刷新時,就不會再次執行這個Action了,

就會避免表單重復提交的問題了。

其二就是session令牌的方式(token)

處理也很方便,只需要在所提交的表單上加一個struts2標簽 <s:token>

註意在該頁面需要導入 <%@taglib prefix="s" uri="/struts-tags"%>

這樣,當瀏覽器第一次訪問這個帶有<s:token>標簽的頁面時,在服務器中,解析<s:token>標簽的類(TokenTag.class),

會生成一個隨機的字符串(這個字符串,查看網頁的源代碼可以看到),並且發送給客戶端的瀏覽器,同時,在服務器中,

會把這個隨機字符串保存到用戶的session對象中。

當第一次提交表單時,在服務器中,會比較客戶端和服務器中分別保存的這個隨機字符串,因為是第一次提交,

所以這兩個字符串相等,然後進行正常的業務處理。第一次提交後,在服務器中的session中保存的這個隨機字符串,

會改變為其他的隨機值,註意,這是很重要的一步!此時,地址欄停留在處理用戶提交數據的Action中,

客戶端中保存的隨機字符串沒有改變,若是刷新頁面,即重復提交,服務器再進行兩個字符串的比較,

會不相等,就會跳轉到name為invalid.token的結果頁面中,這樣就會防止表單重復提交了。

貼上示例代碼

struts_regist.jsp

 1 <%@ taglib prefix="s" uri="/struts-tags" %>
 2 <%--
 3   Created by IntelliJ IDEA.
 4   User: leslie
 5   Date: 17-12-2
 6   Time: 上午10:46
 7   To change this template use File | Settings | File Templates.
 8 --%>
 9 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
10
<html> 11 <head> 12 <title>註冊</title> 13 </head> 14 <body> 15 <form action="${pageContext.request.contextPath}/struts_regist" method="post"> 16 <s:token /> 17 用戶名:<input type="text" name="name"><br> 18 密&nbsp;&nbsp;&nbsp;&nbsp;碼:<input type="password" name="password"><br> 19 <input type="submit" value="註冊"> 20 </form> 21 </body> 22 </html>

struts.xml

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE struts PUBLIC
 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 4     "http://struts.apache.org/dtds/struts-2.3.dtd">
 5 
 6 <struts>
 7     <package name="default" namespace="/" extends="struts-default">
 8         <action name="regist" class="cn.itcast.action.RegistAction">
 9             <result name="invalid.token">/token.jsp</result>
10             <interceptor-ref name="token" />
11             <interceptor-ref name="defaultStack" />
12         </action>
13     </package>
14 </struts>

token.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@taglib prefix="s" uri="/struts-tags"%>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <title>My JSP ‘index.jsp‘ starting page</title>
 7   </head>
 8 
 9   <body>
10     <s:actionerror/>
11   </body>
12 </html>

RegistAction

 1 package com.emuii.action;
 2 
 3 import com.opensymphony.xwork2.ActionSupport;
 4 import org.apache.struts2.ServletActionContext;
 5 
 6 public class RegistAction extends ActionSupport {
 7 
 8     @Override
 9     public String execute() throws Exception {
10 
11        String name = ServletActionContext.getRequest().getParameter("name");
12        String password = ServletActionContext.getRequest().getParameter("password");
13 
14        System.out.println(name+":"+password+"已註冊");
15 
16        return null;
17     }
18 }

如果想要自定義錯誤信息,只需在action同一目錄下創建一個 ----類名.properties配置文件即可

RegistAction.properties

1 struts.messages.invalid.token=\u60A8\u5DF2\u7ECF\u91CD\u590D\u63D0\u4EA4\u8868\u5355\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5

另:對於只有一個action來說,通配符跳轉的方式第一種防表單提交無效的,雖然重定向之後的jsp頁面不一樣。

如果需要對特定的方法進行防表單提交這樣:

1 <action name="someAction" class="com.examples.SomeAction">
2      <interceptor-ref name="token">
3         <param name="includeMethods">myMethod</param>
4      </interceptor-ref name="token"/>
5      <interceptor-ref name="basicStack"/>
6      <result name="success">good_result.ftl</result>
7  </action>

<param name="includeMethod">xx</param>表示只攔截xx方法

<param name="excludeMethod">xx</param>表示攔截xx方法之外的方法

另:WARN [org.apache.struts2.util.TokenHelper] - Could not find token name in params.出現這個問題,

也有可能是你沒對指定方法進行攔截,當然情況不一定非是這種的,只是因為我的項目問題才導致這個問題的。

關於struts2防止表單重復提交