表單重複提交的概述
若刷新表單頁面,再提交表單不算重複提交。
若是重定向,已經提交成功後再刷新不算重複提交。
以下幾種情況算是表單重複提交
多次點擊提交按鈕
已經提交成功,按"回退"之後,再點擊"提交按鈕"
在控制器響應頁面的形式爲轉發情況下,若已經提交成功,然後點擊"刷新"重複提交的缺點
加重了服務器的負擔
可能導致錯誤操作
Struts2解決表單重複提交
在
<s:form >
標籤中添加<s:token>
子標籤
生成一個隱藏域
在session
添加一個屬性值
隱藏域的值和session
的屬性值是一致的使用
Token
或TokenSession
攔截器
這兩個攔截器均不在默認的攔截器棧中,所以需要手工配置一下
若使用Token
攔截器,則需要配置一個token.valid
的result
若使用TokenSession
攔截器,則不需要配置任何其它的result
Token
與TokenSession
區別
都是解決表單重複提交問題,但是使用token
攔截器會轉到token.valid
這個result
,使用tokenSession
攔截器則還會響應那個目標頁面,但不會執行tokenSession
的後續攔截器。可以使用
<s:actionerror>
標籤來顯示重複提交的錯誤消息,該錯誤消息可以在國際化資源文件中覆蓋,該字段名爲struts.messages.invalid.token
,可以在struts-messages.properties
文件中找到。
使用token攔截器的配置示例:
<action name="testToken" class="com.cerr.struts2.TokenAction">
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result>/success.jsp</result>
<result name="invalid.token">/token-error.jsp</result>
</action>
在token-error.jsp中打印錯誤消息:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: 白菜
Date: 2019/8/7
Time: 21:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<s:actionerror></s:actionerror>
</body>
</html>
Struts2攔截器概述
攔截器在訪問某個Action方法之前或之後實施攔截
攔截器是可拔插的,攔截器是AOP的一種實現。
攔截器棧將攔截器按一定的順序聯結成一條鏈,在訪問被攔截的方法時,Struts2攔截器鏈中的攔截器就會按其之前定義的順序被依次調用。
-
攔截器的調用流程
Interceptor接口
Struts會依次調用爲某個Action而註冊的每一個攔截器的
intercept
方法每次調用
intercept
方法時,Struts會傳遞一個ActionInvocation
接口的實例ActionInvocation
代表一個給定ActionAction
的執行狀態,攔截器可以從該類的對象裏獲得與該Action相關聯的Action對象和Result對象,在完成攔截器自己的任務之後,攔截器將調用ActionInvocation
對象的invoke
方法前進到Action處理流程的下一個環節AbstractInterceptor
類實現了Interceptor
接口,併爲init
,destory
提供了一個空白的實現。
自定義攔截器
定義一個攔截器的類
可以實現Interceptor
接口
也可以繼承AbstractInterceptor
抽象類在
struts.xml
文件中配置注意:在自定義的攔截器中可以選擇不調用
ActionInvocation
的invoke()
方法,那麼後續的攔截器和Action方法將不會被調用。Struts2會渲染自定義攔截器intercept
方法返回值對應的result
示例:
定義攔截器類myInterceptor:
package com.cerr.struts2.interceptors;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class myInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("調用actionInvocation.invoke之前");
String result = actionInvocation.invoke();
System.out.println("調用actionInvocation.invoke之後");
return result;
}
}
配置及使用:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<!-- 配置-->
<interceptor name="hello" class="com.cerr.struts2.interceptors.myInterceptor"></interceptor>
</interceptors>
<action name="testToken" class="com.cerr.struts2.TokenAction">
<!-- 使用-->
<interceptor-ref name="hello"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result>/success.jsp</result>
<result name="invalid.token">/token-error.jsp</result>
</action>
</package>
</struts>