Struts2+拦截器InterceptorWord格式文档下载.docx
《Struts2+拦截器InterceptorWord格式文档下载.docx》由会员分享,可在线阅读,更多相关《Struts2+拦截器InterceptorWord格式文档下载.docx(16页珍藏版)》请在冰豆网上搜索。
封装请求参数:
Struts1中强制使用ActionForm对象封装请求的参数。
Struts2可以选择使用POJO类来封装请求的参数,或者直接使用Action的属性。
表达式语言方面:
Struts1中整合了EL,但是EL对集合和索引的支持不强,Struts2整合了OGNL(ObjectGraphNavigationLanguage)。
绑定值到视图技术:
Struts1使用标准的JSP,Struts2使用“ValueStack”技术。
类型转换:
Struts1中的ActionForm基本使用String类型的属性。
Struts2中使用OGNL进行转换,可以更方便的使用。
数据校验:
Struts1中支持覆盖validate方法或者使用Validator框架。
Struts2支持重写validate方法或者使用XWork的验证框架。
Action执行控制的对比:
Struts1支持每一个模块对应一个请求处理,但是模块中的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈为每一个Action创建不同的生命周期。
WebWork和Struts2的对比
从某种程度上看,Struts2是从WebWork2上升级得到的。
甚至Apache的官方文档也讲:
WebWork2到Struts2是平滑的过渡。
我们甚至也可以说Struts2就是WebWork2.3而已。
在很多方面Struts仅仅是改变了WebWork下的名称。
Struts2对应的有自己的标签,并且功能强大。
Webwork也有自己的标签。
二、Struts2原理及流程
1、Struts2体系结构图(官方提供)
2、Struts2的工作机制
1、客户端发出一个指向servlet容器的请求(tomcat);
2、这个请求会经过图中的几个过滤器,最后会到达FilterDispatcher过滤器。
3、过滤器FilterDispatcher是struts2框架的心脏,在处理用户请求时,它和请求一起相互配合访问struts2的底层框架结构。
在web容器启动时,struts2框架会自动加载配置文件里相关参数,并转换成相应的类。
如:
ConfigurationManager、ActionMapper和ObjectFactory。
ConfigurationManager
存有配置文件的一些基本信息;
ActionMapper存有action的配置信息。
在请求过程中所有的对象(Action,Results,
Interceptors,等)都是通过ObjectFactory来创建的。
过滤器会通过询问ActionMapper类来查找请求中
需要用到的Action。
4、如果找到需要调用的Action,过滤器会把请求的处理交给ActionProxy。
ActionProxy为Action的代理对象。
ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类。
5、ActionProxy创建一个ActionInvocation的实例。
ActionInvocation在ActionProxy层之下,它表示了
Action的执行状态,或者说它控制的Action的执行步骤。
它持有Action实例和所有的Interceptor。
6、ActionInvocation实例使用命名模式来调用,1.
ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。
2.
通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。
在调用Action的过程前后,涉及到相关拦截器(intercepetor)的调用。
7.、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。
返回结果
通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。
在表
User-------Filters---FilterDispatcher------ActionMapper-----ActionProxy--------
-----ConfigrationManager(struts.xml)------ActionInvocation-------Intercepters-------
------struts.xml------jsporaction
3.Struts2具体工作流程及代码分析
(1)和Struts1.x不同,Struts2的启动是通过FilterDispatcher过滤器实现的。
下面是该过滤器在web.xml文件中的配置:
<
filter>
<
filter-name>
struts2<
/filter-name>
<
filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
/filter-class>
<
/filter>
filter-mapping>
url-pattern>
/*<
/url-pattern>
/filter-mapping>
Struts2建议,在对Struts2的配置尚不熟悉的情况下,将url-pattern配置为/*,这样该过滤器将截拦所有请求。
实际上,FilterDispatcher除了实现Filter接口以外,还实现了StrutsStatics接口
(2)容器启动后,FilterDispatcher被实例化,调用init(FilterConfigfilterConfig)方法。
该方法创建Dispatcher类的对象,并且将FilterDispatcher配置的初始化参数传到对象中,并负责Action的执行。
然后得到参数packages,值得注意的是,还有另外三个固定的包和该参数进行拼接,分别是org.apache.struts2.static、template、和org.apache.struts2.interceptor.debugging,中间用空格隔开,经过解析将包名变成路径后存储到一个名叫pathPrefixes的数组中,这些目录中的文件会被自动搜寻。
(3)当用户向Struts2发送请求时,FilterDispatcher的doFilter()方法自动调用,这个方法非常关键。
首先,Struts2对请求对象进行重新包装,此次包装根据请求内容的类型不同,返回不同的对象,如果为multipart/form-data类型,则返回MultiPartRequestWrapper类型的对象,该对象服务于文件上传,否则返回StrutsRequestWrapper类型的对象,MultiPartRequestWrapper是StrutsRequestWrapper的子类,而这两个类都是HttpServletRequest接口的实现。
(4)request对象重新包装后,通过ActionMapper的getMapping()方法得到请求的Action,Action的配置信息存储在ActionMapping对象中,该语句mapping=actionMapper.getMapping(request,dispatcher.getConfigurationManager());
。
该方法的具体活动图如下:
getMapping()方法返回ActionMapping类型的对象,该对象包含三个参数:
Action的name、namespace和要调用的方法method。
如果getMapping()方法返回ActionMapping对象为null,则FilterDispatcher认为用户请求不是Action,自然另当别论,FilterDispatcher会做一件非常有意思的事:
如果请求以/struts开头,会自动查找在web.xml文件中配置的packages初始化参数。
init-param>
<
param-name>
packages<
/param-name>
param-value>
com.action<
/param-value>
/init-param>
FilterDispatcher会将com.action包下的文件当作静态资源处理,即直接在页面上显示文件内容,不过会忽略扩展名为class的文件。
比如在com.lizanhong.action包下有一个aaa.txt的文本文件,其内容为“中华人民共和国”,访问http:
//localhost:
8081/Struts2Demo/struts/aaa.txt时会有如图17的输出:
如果用户请求的资源不是以/struts开头——可能是.jsp文件,也可能是.html文件,则通过过滤器链继续往下传送,直到到达请求的资源为止。
(5)如果getMapping()方法返回有效的ActionMapping对象,则被认为正在请求某个Action,将调用Dispatcher.serviceAction(request,response,servletContext,mapping)方法,该方法是处理Action的关键所在。
在Dispatcher.serviceAction()方法中,先加载Struts2的配置文件,如果没有人为配置,则默认加载struts-default.xml、struts-plugin.xml和struts.xml,并且将配置信息保存在形如com.opensymphony.xwork2.config.entities.XxxxConfig的类中。
类com.opensymphony.xwork2.config.providers.XmlConfigurationProvider负责配置文件的读取和解析,addAction()方法负责读取<
action>
标签,并将数据保存在ActionConfig中;
addResultTypes()方法负责将<
result-type>
标签转化为ResultTypeConfig对象;
loadInterceptors()方法负责将<
interceptor>
标签转化为InterceptorConfi对象;
loadInterceptorStack()方法负责将<
interceptor-ref>
标签转化为InterceptorStackConfig对象;
loadInterceptorStacks()方法负责将<
interceptor-stack>
标签转化成InterceptorStackConfig对象。
而上面的方法最终会被addPackage()方法调用,将所读取到的数据汇集到PackageConfig对象中。
具体活动图:
(6)配置信息加载完成后,创建一个Action的代理对象——ActionProxy引用,实际上对Action的调用正是通过ActionProxy实现的,而ActionProxy又由ActionProxyFactory创建,ActionProxyFactory是创建ActionProxy的工厂。
配置信息加载完成后,创建一个Action的代理对象——ActionProxy引用,实际上对Action的调用正是通过ActionProxy实现的,而ActionProxy又由ActionProxyFactory创建,ActionProxyFactory是创建ActionProxy的工厂。
注:
ActionProxy和ActionProxyFactory都是接口,他们的默认实现类分别是DefaultActionProxy和DefaultActionProxyFactory,位于com.opensymphony.xwork2包下。
在这里,我们绝对有必要介绍一下com.opensymphony.xwork2.DefaultActionInvocation类,该类是对ActionInvocation接口的默认实现,负责Action和截拦器的执行。
在DefaultActionInvocation类中,定义了invoke()方法,该方法实现了截拦器的递归调用和执行Action的execute()方法。
所有的截拦器必须实现intercept方法,而该方法的参数恰恰又是ActionInvocation,所以,如果在intercept方法中调用invocation.invoke(),从Action的Intercepor列表中找到下一个截拦器,依此递归。
截拦器的调用活动图:
如果截拦器全部执行完毕,则调用invokeActionOnly()方法执行Action,invokeActionOnly()方法基本没做什么工作,只调用了invokeAction()方法。
(7)为了执行Action,必须先创建该对象,该工作在DefaultActionInvocation的构造方法中调用init()方法早早完成。
调用过程是:
DefaultActionInvocation()->
init()->
createAction()。
Action创建好后,轮到invokeAction()大显身手了,该方法比较长,但关键语句实在很少,用心点看不会很难。
(8)Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。
归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。
以下是调用关系图:
其中:
Ø
ActionProxy:
管理Action的生命周期,它是设置和执行Action的起始点。
ActionInvocation:
在ActionProxy层之下,它表示了Action的执行状态。
它持有Action实例和所有的Interceptor
(9) 以下是Struts2运行时调用方法的顺序图:
二、拦截器的结束与应用
拦截器的工作原理图:
每一个Action请求都包装在一系列的拦截器的内部。
拦截器可以在Action执行直线做相似的操作也可以在Action执行直后做回收操作。
每一个Action既可以将操作转交给下面的拦截器,Action也可以直接退出操作返回客户既定的画面。
自定义一个拦截器的步骤:
1自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
2在strutx.xml中注册上一步中定义的拦截器。
3在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
Interceptor接口声明了三个方法:
publicinterfaceInterceptorextendsSerializable{
voiddestroy();
voidinit();
Stringintercept(ActionInvocationinvocation)throwsException;
}
Init方法在拦截器类被创建之后,在对Action镜像拦截之前调用,相当于一个post-constructor方法,使用这个方法可以给拦截器类做必要的初始话操作。
Destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。
Intercept是拦截器的主要拦截方法,如果需要调用后续的Action或者拦截器,只需要在该方法中调用invocation.invoke()方法即可,在该方法调用的前后可以插入Action调用前后拦截器需要做的方法。
如果不需要调用后续的方法,则返回一个String类型的对象即可,例如Action.SUCCESS。
另外AbstractInterceptor提供了一个简单的Interceptor的实现。
在不需要编写init和destroy方法的时候,只需要从AbstractInterceptor继承而来,实现intercept方法即可。
我们尝试编写一个Session过滤用的拦截器,该拦截器查看用户Session中是否存在特定的属性(LOGIN属性)如果不存在,中止后续操作定位到LOGIN,否则执行原定操作,代码为:
publicclassCheckLoginInterceptorextendsAbstractInterceptor{
publicstaticfinalStringLOGIN_KEY="
LOGIN"
;
publicstaticfinalStringLOGIN_PAGE="
global.login"
publicStringintercept(ActionInvocationactionInvocation)throwsException{
System.out.println("
beginchecklogininterceptor!
"
);
//对LoginAction不做该项拦截
Objectaction=actionInvocation.getAction();
if(actioninstanceofLoginAction){
exitchecklogin,thisisloginaction."
returnactionInvocation.invoke();
}
//确认Session中是否存在LOGIN
Mapsession=actionInvocation.getInvocationContext().getSession();
Stringlogin=(String)session.get(LOGIN_KEY);
if(login!
=null&
&
login.length()>
0){
//存在的情况下进行后续操作。
alreadylogin!
}else{
//否则终止后续操作,返回LOGIN
nologin,forwardloginpage!
returnLOGIN_PAGE;
注册拦截器
interceptors>
<
interceptorname="
login"
class="
com.jpleasure.teamware.util.CheckLoginInterceptor"
/>
interceptor-stackname="
teamwareStack"
>
<
interceptor-refname="
<
defaultStack"
/interceptor-stack>
/interceptors>
将上述拦截器设定为默认拦截器:
default-interceptor-refname="
这样在后续同一个package内部的所有Action执行之前都会被login拦截。
Struts2(XWork)提供的拦截器的功能说明:
拦截器
名字
说明
AliasInterceptor
alias
在不同请求之间将请求参数在不同名字件转换,请求内容不变
ChainingInterceptor
chain
让前一个Action的属性可以被后一个Action访问,现在和chain类型的result(<
resulttype=”chain”>
)结合使用。
CheckboxInterceptor
checkbox
添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。
CookiesInterceptor
cookies
使用配置的name,value来是指cookies
ConversionErrorInterceptor
conversionError
将错误从ActionContext中添加到Action的属性字段中。
CreateSessionInterceptor
createSession
自动的创建HttpSession,用来为需要使用到HttpSession的拦截