struts2的工作流程
用户请求
——> StrutsPrepareAndExecuteFilter
——> Interceptor
——> Action
——> Result
——> Jsp/html
——> 响应
Struts2拦截器
拦截器(interceptor)是Struts2最强大的特性之一,拦截器可以让你在Action和result被执行之前或之后进行一些处理。同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很多特性都是由拦截器来完成的。例如params拦截器将HTTP请求中的参数解析出来,并设置为Action的属性。servlet-config拦截器直接将HTTP请求中的HttpServletRequest对象化HttpServletResponse对象传给Action。
Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特性。这些内置的拦截器在struts-default.xml中配置。只有配置了拦截器,拦截器才可以正常的工作和运行。在struts-default.xml中拦截器的配置片段为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<
package
name
=
"struts-default"
abstract
=
"true"
> ①
<
interceptors
>
<
interceptor
name
=
"alias"
class
=
"com.opensymphony.xwork2.interceptor.AliasInterceptor"
/> ②
<
interceptor
name
=
"autowiring"
class
=
"com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"
/>
//…其他拦截器配置
<
interceptor-stack
name
=
"defaultStack"
> ③
<
interceptor-ref
name
=
"exception"
/>
<
interceptor-ref
name
=
"alias"
/>
<
interceptor-ref
name
=
"servletConfig"
/>
<
interceptor-ref
name
=
"i18n"
/>
//…其他拦截器的引用
</
interceptor-stack
>
</
interceptors
>
<
default-interceptor-ref
name
=
"defaultStack"
/> ④
</
package
>
① package将属性abstract设置为true,代表此package为一个抽象的package。抽象package和非抽象package的区别在于抽象的package中不能配置action。
② name属性指定拦截器的名字,class属性指定拦截器的完全限定名。
③ 多个拦截器可以组成拦截器栈。name属性为拦截器栈的名字。
④ 指定当前package的默认拦截器(栈)。当前指定的默认拦截器栈为defaultStack,该拦截器栈是Struts2运行的一个基本拦截器栈,一般我们不用在自己配置它,因为在大多数情况下,我们自定义的package是继承自struts-default这个package的。
|
我们以Struts2内置的timer拦截器为例,来学习如何在我们的应用中添加其他的拦截器。timer拦截器可以统计action执行的时间。我们可以修改package中默认的拦截器,那么将替换掉struts-default中配置的defaultStack拦截器栈,导致Struts2无法正常运行,比如无法获取表单的值等等。那么该如何正确的配置呢?可以在添加新的拦截器的基础上加入defaultStack拦截器栈,这样就可以保证defaultStack拦截器栈的存在。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<
package
name
=
"myStruts"
extends
=
"struts-default"
>
<
interceptors
>
<
interceptor-stack
name
=
"myInterceptor"
> ①
<
interceptor-ref
name
=
"timer"
/>
<
interceptor-ref
name
=
"defaultStack"
/>
</
interceptor-stack
>
</
interceptors
>
<
default-interceptor-ref
name
=
"myInterceptor"
/> ②
<
action
name
=
"userAction"
class
=
"com.kay.action.UserAction"
>
<
result
name
=
"success"
>suc.jsp</
result
>
<
result
name
=
"input"
>index.jsp</
result
>
<
result
name
=
"error"
>err.jsp</
result
>
</
action
>
</
package
>
① 添加一个自定义的拦截器栈,并在其中包含time拦截器和defaultStack拦截器栈。
② 设置当前的package的默认拦截器栈为自定义的拦截器栈。
|
修改package的默认拦截器会应用的package中的所有Action中,如果只想给其中一个Action添加拦截器,则可以这样来做:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<
package
name
=
"myStruts"
extends
=
"struts-default"
>
<
interceptors
>
<
interceptor-stack
name
=
"myInterceptor"
>
<
interceptor-ref
name
=
"timer"
/>
<
interceptor-ref
name
=
"defaultStack"
/>
</
interceptor-stack
>
</
interceptors
>
<
action
name
=
"userAction"
class
=
"com.kay.action.UserAction"
>
<
interceptor-ref
name
=
"myInterceptor"
/> ①
<
result
name
=
"success"
>suc.jsp</
result
>
<
result
name
=
"input"
>index.jsp</
result
>
<
result
name
=
"error"
>err.jsp</
result
>
</
action
>
</
package
>
① 给UserAction添加拦截器。
|
如果要创建自己的拦截器,只需要实现Interceptor接口,该接口中定义了以下三个方法:
void init():
在拦截器初始化之后,在执行拦截之前,系统调用该方法。对于一个拦截器而言,init方法只会被调用一次。
String intercept(ActionInvocation invocation) throws Exception:
该方法是拦截器的拦截方法,返回一个字符串,系统将会跳转到该字符串对应的视图资源。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该对象的invoke方法,将控制权转给下一个拦截器或者转给Action的execute方法。
void destroy():
该方法与init方法对应,在拦截器示例被销毁之前,系统将会调用该方法。
除了Interceptor接口外,Struts2中还提供了一个AbStractInterceptor类,该类提供了一个init和destroy方法的空实现。如果不需要就不用重写这两个方法,可见继承自AbstractInterceptor类可以让我们构建拦截器时变得简单。
下面我们构建自己的拦截器,实现timer拦截器的效果。
1
2
3
4
5
6
7
8
9
10
11
12
|
public
class
MyInterceptor
extends
AbstractInterceptor {
public
String intercept(ActionInvocation invocation)
throws
Exception {
long
startTime = System.currentTimeMillis(); ①
String result = invocation.invoke(); ②
long
endTime = System.currentTimeMillis(); ③
System.out.println(
"Action执行共需要"
+ (endTime - startTime) +
"毫秒"
);
return
result;
}
}
① 获得Action执行的开始时间。
② 将控制权交给下一个拦截器,如果该拦截器是最后一个拦截器,则调用Action的execute方法。
③ 获得Action执行的结束时间。
|
在配置文件struts.xml中配置拦截器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<
package
name
=
"myStruts"
extends
=
"struts-default"
>
<
interceptors
>
<
interceptor
name
=
"myTimer"
class
=
"com.kay.interceptor.MyInterceptor"
></
interceptor
> ①
<
interceptor-stack
name
=
"myInterceptor"
>
<
interceptor-ref
name
=
"myTimer"
/> ②
<
interceptor-ref
name
=
"defaultStack"
/>
</
interceptor-stack
>
</
interceptors
>
<
action
name
=
"userAction"
class
=
"com.kay.action.UserAction"
>
<
interceptor-ref
name
=
"myInterceptor"
/>
<
result
name
=
"success"
>suc.jsp</
result
>
<
result
name
=
"input"
>index.jsp</
result
>
<
result
name
=
"error"
>err.jsp</
result
>
</
action
>
</
package
>
① 定义一个新的拦截器,name属性为拦截器的名字,class属性为拦截器的完全限定名。
② 在拦截器栈中加入新的拦截器。
|
从拦截器的运行原理上和我们以前学习的Servlet中的过滤器是不是很相像呢?其实它们只有一个重要的区别,就是拦截器的工作是不依赖容器的,这会在进行单元测试时变得简单。
struts2.0中struts.xml配置文件详解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" >
<
struts
>
<!-- include节点是struts2中组件化的方式 可以将每个功能模块独立到一个xml配置文件中 然后用include节点引用 -->
<
include
file
=
"struts-default.xml"
></
include
>
<!-- package提供了将多个Action组织为一个模块的方式
package的名字必须是唯一的 package可以扩展 当一个package扩展自
另一个package时该package会在本身配置的基础上加入扩展的package
的配置 父package必须在子package前配置
name:package名称
extends:继承的父package名称
abstract:设置package的属性为抽象的 抽象的package不能定义action 值true:false
namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/test那么访问是的地址为http://localhost:8080/struts2/test/XX.action
-->
<
package
name
=
"com.kay.struts2"
extends
=
"struts-default"
namespace
=
"/test"
>
<
interceptors
>
<!-- 定义拦截器
name:拦截器名称
class:拦截器类路径
-->
<
interceptor
name
=
"timer"
class
=
"com.kay.timer"
></
interceptor
>
<
interceptor
name
=
"logger"
class
=
"com.kay.logger"
></
interceptor
>
<!-- 定义拦截器栈 -->
<
interceptor-stack
name
=
"mystack"
>
<
interceptor-ref
name
=
"timer"
></
interceptor-ref
>
<
interceptor-ref
name
=
"logger"
></
interceptor-ref
>
</
interceptor-stack
>
</
interceptors
>
<!-- 定义默认的拦截器 每个Action都会自动引用
如果Action中引用了其它的拦截器 默认的拦截器将无效 -->
<
default-interceptor-ref
name
=
"mystack"
></
default-interceptor-ref
>
<!-- 全局results配置 -->
<
global-results
>
<
result
name
=
"input"
>/error.jsp</
result
>
</
global-results
>
<!-- Action配置 一个Action可以被多次映射(只要action配置中的name不同)
name:action名称
class: 对应的类的路径
method: 调用Action中的方法名
-->
<
action
name
=
"hello"
class
=
"com.kay.struts2.Action.LoginAction"
>
<!-- 引用拦截器
name:拦截器名称或拦截器栈名称
-->
<
interceptor-ref
name
=
"timer"
></
interceptor-ref
>
<!-- 节点配置
name : result名称 和Action中返回的值相同
type : result类型 不写则选用superpackage的type struts-default.xml中的默认为dispatcher
-->
<
result
name
=
"success"
type
=
"dispatcher"
>/talk.jsp</
result
>
<!-- 参数设置
name:对应Action中的get/set方法
-->
<
param
name
=
"url"
>http://www.sina.com</
param
>
</
action
>
</
package
>
</
struts
>
|
本文转自lixiyu 51CTO博客,原文链接:http://blog.51cto.com/lixiyu/1355147,如需转载请自行联系原作者