1
Struts2 拦截器
2
第三章:Struts2拦截器
目标:
本章旨在向学员介绍:
1)理解Struts2的工作原理
2)理解Struts2拦截器的工作方式
3)掌握拦截器的配置
4)会自定义拦截器
时间:3学时
教学方法:授课+练习
3
第三章 Struts2拦截器
• 本章内容
¾ 3.1 Struts2工作原理
¾ 3.2 拦截器概述
¾ 3.3 拦截器的配置
¾ 3.4 自定义拦截器
¾ 3.5 自定义拦截器综合应用--权限验证
4
3.1.1 Struts2工作原理
5
• Controller
– Filter 为Struts2拦截指定的URL请求;
– Interceptors 拦截器,在调用Action前或之后由拦截器对请
求进行预处理,或后处理;
• Model
– Action 处理业务逻辑,并为页面提供输出的数据;
• View
– JSP 显示页面。
3.1.1 Struts2工作原理
6
3.1.1 Struts2工作原理
• 配置文件
7
3.1.1 Struts2工作原理
8
3.1.2 Struts2核心组件
• Struts2的Servlet过滤器StrutsPrepareAndExecuteFilter
• ActionMapper
• ActionProxy
• ActionInvocation
• Interceptor
9
3.1.3 Struts2基本工作过程
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请
求
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有
一个叫做ActionContextCleanUp的可选过滤器,这个过滤
器对于Struts2和其他框架的集成很有帮助,例如:
SiteMesh Plugin);
3、接着StrutsPrepareAndExecuteFilter被调用,
StrutsPrepareAndExecuteFilter询问ActionMapper来决定
这个请求是否需要调用某个Action;
4、如果ActionMapper决定需要调用某个Action,
StrutsPrepareAndExecuteFilter把请求的处理交给
ActionProxy;
10
3.1.3 Struts2基本工作过程
5、ActionProxy通过ConfigurationManager询问框架的配置文
件,找到需要调用的Action类;
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action
的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据
struts.xml中的配置找到对应的返回结果。返回结果通常是
(但不总是,也可能是另外的一个Action链)一个需要被
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示的JSP或者FreeMarker的模版。在表示的过程中可以使
用Struts2框架中继承的标签。在这个过程中需要涉及到
ActionMapper。
11
第三章 Struts2拦截器
• 本章内容
¾ 3.1 Struts2工作原理
¾ 3.2 拦截器概述
¾ 3.3 拦截器的配置
¾ 3.4 自定义拦截器
¾ 3.5 自定义拦截器综合应用--权限验证
12
3.2.1 拦截器的概念
• 拦截器(Interceptor)是Struts2的核心组成部分。很多功能都是构建在
拦截器基础之上的,例如文件的上传和下载、国际化、转换器和数据
校验等,Struts2利用内建的拦截器,完成了框架内的大部分操作。
• 在Struts2文档中对拦截器的解释为--拦截器是动态拦截Action调用
的对象。它提供了一种机制,使开发者可以定义一个特定的功能模块
,这个模块可以在Action执行之前或者之后运行,也可以在一个
Action执行之前阻止Action执行。同时也提供了一种可以提取Action
中可重用的部分的方式。
• 拦截器是Struts2 更高层次的解耦,无须侵入框架本身便可以添加新
的功能。
• 拦截器是AOP( Aspect-Oriented Programming)的一种实现,底层
通过动态代理模式完成。
13
3.2.2 Struts2拦截器实现原理
Struts 2的拦截器实现相对简
单。当请求到达Struts 2的
StrutsPrepareAndExecuteFilter
时,Struts 2会查找配置文
件,并根据其配置实例化相对
的拦截器对象,然后串成一个
列表(list),最后一个一个
地调用列表中的拦截器 。
14
3.2.2 Struts2拦截器实现原理
• 拦截器围绕着Action和Result的执行而执行,其工作方式如上
图。
• 从图中可以看到,在Action和Result执行之前,为Action配置
的拦截器将首先被执行,在Action和Result执行之后,拦截器
将重新获得控制权,然后按照与先前调用相反的顺序依次执行
。在整个执行过程中,任何一个拦截器都可以选择直接返回,
从而终止余下的拦截器、Action和Result的执行。例如:当一
个未授权的用户访问受保护的资源时,执行身份验证的拦截器
可以直接返回。
15
3.2.3 拦截器与过滤器区别
区别:
• 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
• 拦截器不依赖与servlet容器,而过滤器依赖与servlet容器。
• 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的
请求起作用。
• 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
16
3.2.4 Struts2内置拦截器
Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-
default.xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;
class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的struts-
default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
17
3.2.4 Struts2内置拦截器
18
第三章 Struts2拦截器
• 本章内容
¾ 3.1 Struts2工作原理
¾ 3.2 拦截器概述
¾ 3.3 拦截器的配置
¾ 3.4 自定义拦截器
¾ 3.5 自定义拦截器综合应用--权限验证
19
3.3.1 拦截器的配置
• 拦截器的配置是在struts.xml中完成的,定义一个拦截器使用
标签,其格式如下:
•
• 这种情况的应用非常广。有的时候,如果需要在配置拦截器时就为
其传入拦截器参数,只要在
与之间配
置标签即可传入相应的参数。其格式如下:
参数值
...//如果需要传入多个参数,可以一并设置
20
3.3.1 拦截器的配置
• 如果在其他的拦截器配置中出现了同名的参数,则前面配置的参数将被
覆盖掉。
在struts.xml中可以配置多个拦截器,它们被包在
之间,例如下面的配置:
...
...//action配置
21
3.3.1 拦截器的配置
• 拦截器是配置在包下的。在包下配置了一系列的拦截器,但仅
仅是配置在该包下,并没有得到应用。如果要应用这些拦截器
,就需要在配置中引用这些拦截器,
格式为:
• 例子:
22
3.3.2 拦截器栈
• 在很多时候,有些指定的拦截器需要被多个Action所使用,这
个时候,如果我们为每一个Action都分别配置拦截器的话,不
仅麻烦,而且不利后期的维护,此时就需要用到拦截器栈。
• 所谓拦截器栈就是将一些拦截器组合起来进行统一管理。格式
为:
• 其实,在Struts 2框架中也配置有很多拦截器栈,在Struts 2的
struts-default.xml中可以发现有如下拦截器栈的配置。
23
3.3.2 拦截器栈
• 拦截器栈配置完成后就可以在中对其引用了,一个action引
用拦截器栈的格式如下:
• 注意:一旦继承了struts-default包(package),所有Action都会
默认调用拦截器栈 ---defaultStack。但是当在Action配置中加入
“”则会覆盖defaultStack,所以在
action中写拦截器引用时,需要显示引用defaultStack(而且最好在
第一句)。
24
3.3.3 默认拦截器
•
• 如果为Action指定了拦截器,则默认拦截器不再起作用,必须
显式指定默认截拦器
25
第三章 Struts2拦截器
• 本章内容
¾ 3.1 Struts2工作原理
¾ 3.2 拦截器概述
¾ 3.3 拦截器的配置
¾ 3.4 自定义拦截器
¾ 3.5 自定义拦截器综合应用--权限验证
26
3.4 自定义拦截器
• 虽然,Struts 2为我们提供如此丰富的拦截器实现,但是这并
不意味我们失去创建自定义拦截器的能力,恰恰相反,在
Struts 2自定义拦截器是相当容易的一件事。
• Struts2的拦截器必须是无状态的。
27
3.4.1自定义拦截器的实现方法
• 其实现方法有:
– 实现Interceptor接口
– 继承AbstractInterceptor类
– 继承MethodFilterInterceptor类
28
3.4.2 Interceptor接口
• Struts 2提供了com.opensymphony.xwork2.interceptor.Interceptor接口,程
序员只要实现该接口就可完成自定义拦截器类的编写。该接口的代码如下:
• 该接口中有如下三种方法:
init():该方法在拦截器被实例化之后、拦截器执行之前调用。该方法只
被执行一次,主要用于初始化资源。
intercept(ActionInvocation invocation):该方法用于实现拦截的动作。该
方法有个参数,用该参数调用invoke()方法,将控制权交给下一个拦截器,
或者交给Action类的方法。
destroy():该方法与init()方法对应,拦截器实例被销毁之前调用。用于
销毁在init()方法中打开的资源。
public interface Interceptor extends Serializable{
void init();
String intercept(ActionInvocation invocation) throws Exception;
void destroy();
}
29
3.4.3 自定义拦截器--实现Interceptor接口
• TimerInterceptor.java
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class TimerInterceptor implements Interceptor
{
public void destroy(){}
public void init(){}
public String intercept(ActionInvocation invocation) throws Exception
{
long startTime = System.currentTimeMillis();
String result = invocation.invoke();
long executionTime = System.currentTimeMillis() - startTime;
System.out.println("Action的执行花费的毫秒数是:" + executionTime);
return result;
}}
30
3.4.3 自定义拦截器--实现Interceptor接口
• Struts.xml
index.jsp
31
3.4.4 AbstractInterceptor类
• 除了Interceptor接口之外,Struts 2框架还提供了
AbstractInterceptor类,该类实现了Interceptor接口,并提供了
init()方法和destroy()方法的空实现。在一般的拦截器实现中,
都会继承该类,因为一般实现的拦截器是不需要打开资源的,
故无须实现这两种方法,继承该类会更简洁。该类的代码实现
为:
public interface AbstractInterceptor implements Interceptor{
public void init(){
}
public void destroy(){
}
public abstract String intercept(ActionInvocation invocation) throws Exception;
}
32
3.4.5自定义拦截器--继承 AbstractInterceptor类
• 拦截器类 MyInterceptor.java
import com.opensymphony.xwork2.ActionInvocation;
Import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor{
public String intercept(ActionInvocation arg0) throws
Exception {
System.out.println("我在Action前执行---->");
String result=arg0.invoke();
System.out.println("我在Action后执行---->");
return result;
}
}
import
com.opensymphony.xwork2.ActionSupport;
public class TestAction extends ActionSupport{
public String execute() throws Exception {
System.out.println("我在Action中执
行---->");
return NONE; //不做任何跳
转
}
}
Action类 TestAction.java
33
• Struts.xml
3.4.5自定义拦截器--继承 AbstractInterceptor类
34
3.4.5自定义拦截器--继承 AbstractInterceptor类
• 练习
将上面TimerInterceptor.java的代码进行修改改为
继承AbstractInterceptor类。
35
3.4.6 MethodFilterInterceptor类
Struts 2框架还提供了
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor
抽象类,该类继承了AbstractInterceptor类,这个拦截器可以
指定要拦截或排除的方法列表。通常情况下,拦截器将拦截
Action的所有方法调用,但在某些应用场景中,对某些方法的拦
截将会出现一些问题。例如:对表单字段进行验证的拦截器,当
我们通过doDefault()方法输出表单时,该方法不应该被拦截,因
此此时表单字段都没有数据。
m2
m1, m3, m4
36
3.4.6 MethodFilterInterceptor类
• 在struts2中,从MethodFilterInterceptor继承的拦截器类有:
– TokenInterceptor
– TokenSessionStoreInterceptor
– DefaultWorkflowInterceptor
– ExecuteAndWaitInterceptor
– ValidationInterceptor
– ParametersInterceptor
– PrepareInterceptor
• MethodFilterInterceptor通过指定included/excluded方法列表来选择
拦截器或排除的方法,可以设置的参数如下:
excludeMethods-------要排除的方法。
includeMethods--------要拦截的方法。
• 例如:有如下的拦截器配置:
input,back,cancel
execute
37
3.4.6 MethodFilterInterceptor类
• 当执行Action的input、back和cancel方法时,验证拦截器将不执行对
输入数据的验证。当执行Action的execute方法时,验证拦截器将执
行对输入数据的验证。
• 在设置拦截器或排除的方法时,如果有多个方法,那么以逗号(,)分隔
,如上所示。如果一个方法的名字同时出现在execludeMethods和
includeMethods参数中,那么它会被当作要拦截的方法。也就是说
, includeMethods优先于execludeMethods。
• 在编写拦截器类的时候要注意,拦截器必须是无状态的,换句话说
,在拦截器类中不应该有实例变量。这是因为struts2对每一个Action
的请求使用的是同一个拦截器实例来拦截调用,如果拦截器有状态,
在多个线程(客户端的每个请求将由服务器端的一个线程来服务)同时
访问一个拦截器实例的情况下,拦截器的状态将不可预测。
38
第三章 Struts2拦截器
• 本章内容
¾ 3.1 Struts2工作原理
¾ 3.2 拦截器概述
¾ 3.3 拦截器的配置
¾ 3.4 自定义拦截器
¾ 3.5 自定义拦截器综合应用--权限验证
39
3.5 自定义拦截器综合应用--权限验证
• 拦截器类ValidateInterceptor.java:
package com.neusoft.interceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class ValidateInterceptor implements Interceptor {
public void destroy() { }
public void init() { }
public String intercept(ActionInvocation invocation) throws Exception {
Object user=ActionContext.getContext().getSession().get("user");
if(user!=null)
{
return invocation.invoke();
}
ActionContext.getContext().getSession().put("message", "没有权限访问");
return "message";}}
40
3.5 自定义拦截器综合应用--权限验证
• action类LoginAction.java
package com.neusoft.interceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
private String username;
private String password;
public String getUsername() {return username;}
public void setUsername(String username) {this.username = username;}
public String getPassword() {return password;}
public void setPassword(String password) {
this.password = password;}
public String execute()
{
if(username.equals("admin") && password.equals("admin"))
{ActionContext.getContext().getSession().put("user", username);
return SUCCESS;}else
return "message";}}
41
3.5 自定义拦截器综合应用--权限验证
• login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%>
My JSP 'login.jsp' starting page
42
3.5 自定义拦截器综合应用--权限验证
• Struts.xml
/success.jsp
/error.jsp
/show.jsp
/error.jsp
43
本章小结
• 理解struts2的工作原理
• 理解拦截器的工作原理
• 掌握拦截器的配置
• 理解拦截器栈
• 会自定义拦截器
44