S8.1_Struts2_Interceptor 拦截器的原理 拦截器与过滤器的区别 自定义拦截器 拦截器防止表单重复提交
来源:互联网 发布:知乎 匿名用户 编辑:程序博客网 时间:2024/06/05 18:10
拦截器的原理
拦截器与过滤器的区别
自定义拦截器
拦截器防止表单重复提交
拦截器是struts2框架的核心,struts2中包括解析请求参数,将请求参数赋值给action属性,
执行数据校验,文件上传等工作都是通过拦截器实现的,struts2设计的灵巧性,更大程度地得益于
拦截器设计,当需要扩展struts2功能时,只需要提供对应拦截器,并将它配置在struts2容器中即可;
如果不需要该功能时,也只需要取消该拦截器的配置即可。
struts2内置了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中,其中
name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的
package继承了struts2的默认struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
常见的内置拦截器
1. chain: 两个action服务器内部跳转执行的一个拦截器
2. execAndWait: 当执行一个动作在后台执行的时间比较长,在等待的过程中它会转向的去显示一个等待页面
3. fileUpload: 文件上传时执行的一个拦截器
4. timer: 某一个动作执行时间的拦截器
5. token: 解决表单重复提交要使用的一个拦截器
6. token-session 解决表单重复提交要使用的一个拦截器
拦截器与过滤器的区别
1. 拦截器拦截的是动作(action),过滤器过滤的是请求(request),一般映射为/*,表示过滤所有请求;
2. 拦截器是基于java反射机制的,而过滤器是基于函数回调的;
3. 过滤器依赖于servlet容器,而拦截器不依赖于servlet容器;
4. 拦截器可以访问Action上下文,值栈里的对象,而过滤器不能;
5. 在action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次;
自定义拦截器
Interceptor 不推荐使用这个接口
AbstractInterceptor 推荐继承这个抽象类,它也实现了Interceptor这个接口,继承后只需要实现intercept这个抽象方法即可;对所有方法进行拦截
MethodFilterInterceptor 推荐继承MethodFilterInterceptor类,它继承了AbstractInterceptor类;对指定方法进行拦截
我们接下来将要创建的项目目录结构如下:
由项目S4.5_Struts2_ActionAdvance(如何下载它)复制生成一个新项目S8.1_Struts2_Interceptor
自定义拦截器如何继承AbstractInterceptor这个抽象类实现:
第1步:新建net.nw.interceptor包,并在该包内新建TestInterceptor1.java自定义拦截器类
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class TestInterceptor1 extends AbstractInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor1拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor1拦截之后执行的动作...");
return result;
}
}
第2步:在src/struts.xml配置文件中找到父包default,配置自定义拦截器testInterceptor1 :
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第3步:在src/struts.xml配置文件中找到子包user,将自定义拦截器的拦截器堆栈 mydefaultStack应用到user包中名称为login的action中:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第4步:发布运行程序,测试效果截图如下:
第5步:为测试拦截效果,找到net.nw.action包下名称为UserAction.java的动作类,在execute()方法中插入代码System.out.println("普通用户登录 ...");
这样就能看到自定义拦截器的拦截效果了,再次发布运行程序,测试效果截图如下:
接下来演示在一个自定义堆栈<interceptor-stack name="mydefaultStack">里一共定义3个拦截器,看一下它们是按照怎样的顺序执行?
第1步:找到net.nw.interceptor包,在该包内新建TestInterceptor2.java自定义拦截器类
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class TestInterceptor2 extends AbstractInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor2拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor2拦截之后执行的动作...");
return result;
}
}
第2步:找到net.nw.interceptor包,在该包内新建TestInterceptor3.java自定义拦截器类
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class TestInterceptor2 extends AbstractInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor3拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor3拦截之后执行的动作...");
return result;
}
}
第3步:在一个自定义堆栈<interceptor-stack name="mydefaultStack">里一共定义3个拦截器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor name="testInterceptor2" class="net.nw.interceptor.TestInterceptor2" />
<interceptor name="testInterceptor3" class="net.nw.interceptor.TestInterceptor3" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1"></interceptor-ref>
<interceptor-ref name="testInterceptor2"></interceptor-ref>
<interceptor-ref name="testInterceptor3"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第4步:发布运行程序,测试效果截图如下:
自定义拦截器如何继承MethodFilterInterceptor 这个类实现:
第1步:在src/struts.xml配置文件中找到子包user,将自定义拦截器<interceptor-ref name="mydefaultStack"></interceptor-ref>添加插入到name="*_*"的action中
接着上面的范例代码继续,其它地方代码保持不变,只插入红色字体标识的代码 --------- 这样增删改方法的执行都会被拦截:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor name="testInterceptor2" class="net.nw.interceptor.TestInterceptor2" />
<interceptor name="testInterceptor3" class="net.nw.interceptor.TestInterceptor3" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1"></interceptor-ref>
<interceptor-ref name="testInterceptor2"></interceptor-ref>
<interceptor-ref name="testInterceptor3"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第2步:发布运行程序,测试效果截图如下:
接着上面演示只拦截添加和删除方法的实验步骤:
第1步:在net.nw.interceptor包下,让TestInterceptor1拦截类继承 MethodFilterInterceptor类,TestInterceptor1.java实现的代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor1 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor1拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor1拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor1拦截之后执行的动作...");
return result;
}
}
第2步:在net.nw.interceptor包下,让TestInterceptor2拦截类继承 MethodFilterInterceptor类,TestInterceptor2.java实现的代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor2 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor2拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor2拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor2拦截之后执行的动作...");
return result;
}
}
第3步:在net.nw.interceptor包下,让TestInterceptor3拦截类继承 MethodFilterInterceptor类,TestInterceptor3.java实现的代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor3 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("TestIntercptor3拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor3拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor3拦截之后执行的动作...");
return result;
}
}
第4步:在 src/struts.xml配置文件中找到父包default,在3个自定义interceptor-ref中都配置<param name="excludeMethods">delete</param>,
表示除删除方法之外的方法都会被拦截:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor name="testInterceptor2" class="net.nw.interceptor.TestInterceptor2" />
<interceptor name="testInterceptor3" class="net.nw.interceptor.TestInterceptor3" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1">
<param name="excludeMethods">delete</param>
</interceptor-ref>
<interceptor-ref name="testInterceptor2">
<param name="excludeMethods">delete</param>
</interceptor-ref>
<interceptor-ref name="testInterceptor3">
<param name="excludeMethods">delete</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第5步:发布运行程序,测试效果截图如下:
上面这种配置拦截效果与下两种配置拦截效果一样:
接下来介绍使用PreResultListener在返回结果之前执行一个方法(执行插入点在 执行action之后与excute()方法内部返回result之前的位置),实验步骤如下:
第1步:在net.nw.interceptor包下创建一个名称为BeforeResultInterceptor.java的类,就翻译成前置返回结果监听器吧,并实现PreResultListener接口:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.PreResultListener;
public class BeforeResultInterceptor implements PreResultListener{
@Override
public void beforeResult(ActionInvocation invocation, String result) {
// TODO Auto-generated method stub
System.out.println("beforeResult方法第2个输入参数的值等于:"+result);
System.out.println("返回结果集之前执行beforeResult()方法......");
}
}
第2步:将实现的前置返回结果监听器添加到自定义的拦截器(TestInterceptor1)里,实现一个像拦截器的功能,因而不需要再添加什么配置到struts.xml文件当中,
但它(BeforeResultInterceptor)不是拦截器,TestInterceptor1代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor1 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
invocation.addPreResultListener(new BeforeResultInterceptor());
System.out.println("TestIntercptor1拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor1拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor1拦截之后执行的动作...");
return result;
}
}
第3步:将实现的前置返回结果监听器添加到自定义的拦截器(TestInterceptor1)里,实现一个像拦截器的功能,因而不需要再添加什么配置到struts.xml文件当中,
但它(BeforeResultInterceptor)不是拦截器,TestInterceptor2代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor2 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
invocation.addPreResultListener(new BeforeResultInterceptor());
System.out.println("TestIntercptor2拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor2拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor2拦截之后执行的动作...");
return result;
}
}
第4步:将实现的前置返回结果监听器添加到自定义的拦截器(TestInterceptor1)里,实现一个像拦截器的功能,因而不需要再添加什么配置到struts.xml文件当中,
但它(BeforeResultInterceptor)不是拦截器,TestInterceptor3代码如下:
package net.nw.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class TestInterceptor3 extends MethodFilterInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
invocation.addPreResultListener(new BeforeResultInterceptor());
System.out.println("TestIntercptor3拦截之前执行的动作...");
String result = invocation.invoke();
System.out.println("TestIntercptor3拦截之后invocation.invoke()返回的值:"+result);
System.out.println("TestIntercptor3拦截之后执行的动作...");
return result;
}
}
第5步:发布运行程序,测试效果截图如下:
使用拦截器解防止表单重复提交
<!-- 显示重复提交出错的页面 -->
<interceptor-ref name="token"></interceptor-ref>
<!-- 显示提交成功的页面,但是并不执行重复提交的动作 -->
<interceptor-ref name="tokenSession"></interceptor-ref>
<result name="invalid.token">/token_error.jsp</result>
第1种防止表单重复提交的办法是使用token
第1步:创建一个重复提交出错的页面,名称为token_error.jsp,页面代码如下:
<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<center>
<h1>重复提交提示</h1>
<hr>
请您不要重复提交!
</center>
</body>
</html>
第2步:在配置文件struts.xml中找到父包default,然后在拦截器末尾找到默认的堆栈defaultStack拦截器
在默认堆栈拦截器<interceptor-ref name="defaultStack"></interceptor-ref>上面的位置
配置显示重复提交出错的页面的token拦截器
<interceptor-ref name="token"></interceptor-ref>
还是在父包default内部的下面的<global-results>全局结果集,然后在<global-results></global-results> 末尾的位置
配置<result name="invalid.token">/token_error.jsp</result> ,此步干的事情红色字体的代码已被标识出来了,struts.xml文件的代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor name="testInterceptor2" class="net.nw.interceptor.TestInterceptor2" />
<interceptor name="testInterceptor3" class="net.nw.interceptor.TestInterceptor3" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1">
</interceptor-ref>
<interceptor-ref name="testInterceptor2">
</interceptor-ref>
<interceptor-ref name="testInterceptor3">
</interceptor-ref>
<!-- 显示重复提交出错的页面 -->
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
<result name="invalid.token">/token_error.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
<interceptor-ref name="mydefaultStack">
<param name="testInterceptor1.includeMethods">add,modify</param>
<param name="testInterceptor2.includeMethods">add,modify</param>
<param name="testInterceptor3.includeMethods">add,modify</param>
</interceptor-ref>
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
第3步:我们需要在WebRoot/login.jsp页面生成一个随机令牌,注意红色字体标识的代码,login.jsp页面代码如下:
<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
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">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<center>
<h1>系统登录</h1>
<hr>
<form name="loginForm" action="<%=path%>/user/login.action" method="post" >
用户名称:<input type="text" name="username"/><br>
用户密码:<input type="password" name="password"/><br>
<input type="submit" value="登录"/><br>
<br>
<br><a href="<%=path%>/admin/login.action">管理员登录</a>
<s:token></s:token><!-- 生成一个随机令牌 -->
</form>
</center>
</body>
</html>
第4步:发布运行程序,测试效果截图如下:
第2种防止表单重复提交办法是使用tokenSession,其它的都不变,把struts.xml配置文件中的token改成tokenSession即可,差别是不会跳转到提示重复提交这一页
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" ></constant>
<constant name="struts.i18n.encoding" value="utf-8" ></constant>
<!-- 父包default -->
<package name="default" namespace="" extends="struts-default">
<interceptors>
<interceptor name="testInterceptor1" class="net.nw.interceptor.TestInterceptor1" />
<interceptor name="testInterceptor2" class="net.nw.interceptor.TestInterceptor2" />
<interceptor name="testInterceptor3" class="net.nw.interceptor.TestInterceptor3" />
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="testInterceptor1">
</interceptor-ref>
<interceptor-ref name="testInterceptor2">
</interceptor-ref>
<interceptor-ref name="testInterceptor3">
</interceptor-ref>
<!-- 显示提交成功的页面,但是并不执行重复提交的动作 -->
<interceptor-ref name="tokenSession"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<global-results>
<result name="login_success">/login_success.jsp</result>
<result name="login_failure">/login_failure.jsp</result>
<result name="invalid.token">/token_error.jsp</result>
</global-results>
<action name="exit">
<result>/login.jsp</result>
</action>
</package>
<package name="error" namespace="" extends="default">
<action name="*">
<result>/error.jsp</result>
</action>
</package>
<!-- 子包user继承于父包default -->
<package name="user" namespace="/user" extends="default">
<global-results>
<result>/user/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.UserAction">
<interceptor-ref name="mydefaultStack"></interceptor-ref>
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
<interceptor-ref name="mydefaultStack">
<param name="testInterceptor1.includeMethods">add,modify</param>
<param name="testInterceptor2.includeMethods">add,modify</param>
<param name="testInterceptor3.includeMethods">add,modify</param>
</interceptor-ref>
</action>
</package>
<!-- 子包admin继承于父包default -->
<package name="admin" namespace="/admin" extends="default">
<global-results>
<result>/admin/result.jsp</result>
</global-results>
<action name="login" class="net.nw.action.AdminAction">
<result>/admin/admin.jsp</result>
</action>
<action name="admin" class="net.nw.action.AdminAction">
</action>
<action name="*_*" class="net.nw.action.{1}Action" method="{2}">
</action>
</package>
</struts>
本项目的下载地址:
- S8.1_Struts2_Interceptor 拦截器的原理 拦截器与过滤器的区别 自定义拦截器 拦截器防止表单重复提交
- 使用拦截器防止表单重复提交
- springmvc 拦截器 防止重复提交表单
- 拦截器及防止表单重复提交
- 基于struts2的令牌拦截器,防止表单重复提交
- struts 拦截器设置防止表单的重复提交
- struts 拦截器设置防止表单的重复提交
- 拦截器与过滤器的区别
- struts2拦截器与过滤器的区别
- 过滤器与拦截器的区别
- 拦截器与过滤器的区别
- 拦截器与过滤器的区别
- 过滤器与拦截器的区别
- 过滤器与拦截器的区别
- 过滤器与拦截器的区别
- 过滤器与拦截器的区别
- 过滤器与拦截器的区别
- 过滤器与拦截器的区别
- java中数据结构
- 在canvas中应用font-awesome字体
- javascript字典数据结构Dictionary实现
- 机器学习实战学习笔记6——AdaBoost
- 初级小白改bug心得
- S8.1_Struts2_Interceptor 拦截器的原理 拦截器与过滤器的区别 自定义拦截器 拦截器防止表单重复提交
- BZOJ1877: [SDOI2009]晨跑
- 网络编程中的select实现超时检测和通用API
- 【Hadoop】Sqoop部署入门指南
- 编译uboot遇到/bin/sh: dtc: 未找到命令 make[2]: *** [arch/arm/dts/zynq-zc702.dtb] 错误 127
- 计算x的y次方的值
- 类型转换
- 留言板------Ajax与mysql数据交互01
- ContentProvider