1. 程式人生 > >Struts2 表單重複提交問題

Struts2 表單重複提交問題

1.什麼是重複提交

在不重新整理表單頁面的情況下

  • 》多次點選提交按鈕
  • 》已經提交成功了,按“回退”之後,再點選"提交按鈕"
  • 》在控制器相應頁面的形式為轉發的情況下,已經提交成功,然後點選重新整理或者f5

注意:

  • 》若重新整理表單頁面,再提交表單就不是重複提交
  • 》若使用redirect的相應型別,已經提交成功之後,再點選"重新整理",不算是重複提交

    表單重複提交的危害

  • 增加伺服器的負擔

  • 導致程式錯誤


    解決的方式:Token攔截器或者TokenSession攔截

一、在s:form中新增一個子標籤s:token

  •  這個子標籤會生成一個隱藏域
  • 在session新增一個屬性值

隱藏域和session的屬性值一致就提交成功

二 使用Token或TokenSession攔截器

》這兩個攔截器均不在預設的攔截器棧中,所以需要手工配置一下

》若使用Token攔截器,則需要配置token.valid的result

》若使用TokenStack攔截器,則不需要為他配置任何其他的result

三、Token vs TokenStack

》都是解決表單重複提交問題的

》使用token攔截器,則需要配置一個token.valid的result

》若使用TokenSession攔截器,則還會響應那個目標頁面,但是不會執行tockenSession之後的攔截器,跟什麼也沒有發生一樣

四、可以使用s:actionerror標籤來顯示重複提交的錯誤訊息

該錯誤訊息可以在國際資原始檔中覆蓋,該訊息可以在struts-messages.properties檔案中找到


demo如下

jsp表單頁面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>表單重複提交的問題</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
  </head> 
  <body>
  <s:form action="texttoken">
  <s:token></s:token>
  <s:textfield label="name" name="username"></s:textfield>
  <s:submit></s:submit>
  </s:form>
  </body>
</html>

struts.xml

<action name="texttoken" class="cn.com.app.TextToken">
		<interceptor-ref name="token"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result>/success.jsp</result>
			<result name="invalid.token">/error.jsp</result>
		</action>

Action類

package cn.com.app;
import com.opensymphony.xwork2.ActionSupport;
public class TextToken extends ActionSupport {
	private String username;

	public void setUsername(String username) {
		this.username = username;
	}

	public String getUsername() {
		return username;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.out.println(username);
		return super.execute();
	}
}

錯誤資訊頁面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>錯誤資訊</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
  </head> 
  <body>
  <s:actionerror/>
  </body>
</html>

當我們在前臺頁上輸入一個名字的時候,點選提交到了提交成功的頁面,點選重新整理,就會出現報錯頁面、顯示錯誤資訊

 

如果使用的是tokenSession攔截器的話,就如下操作就可以了

<action name="texttoken" class="cn.com.app.TextToken">
        <interceptor-ref name="tokenSession"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <result>/success.jsp</result>
            <!-- <result name="invalid.token">/error.jsp</result> -->
        </action>

頁面也不會列印錯誤資訊,就跟什麼也沒有發生一樣