前言-
学习Struts初期一直有个疑问,虽然早就听闻Struts-interceptor的大名,但却一直没有实际使用过他,甚至连配置文件里也不见踪影,动作Action则是随处可见。但是在框架后台工作的拦截器interceptor才是真正的英雄。在struts-default包中的默认拦截器栈defaultStack已经处理了大部分的基础任务,从数据转移到异常处理。也正是有了这一套丰富的内建拦截器,你可以坐享其成,使用defaultStack而非自己编写拦截器interceptor。但是学习理解并创建自己的拦截器仍是十分必要的。
关于struts-default包,她在struts2-core-2.x.x jar下,你可以使用解压软件解压并找到她,查看它的代码有助于理解defaultStack都包含什么拦截器,以及他们的顺序。
关于使用struts-default包,平时在struts.xml中的编写package都会继承她(继承她才能在后面使用defalultStack。。。)
本文为个人《Struts2 in Action》的学习笔记,如有错误请及时通知我。
正文-
ActionInvocation:
每当一个Action被触发,框架不是简单的调用Action的execute()方法,而是创建一个名为ActionInvocation的对象,她包含着动作和一系列的拦截器,大概是这个样子的:
ActionInvocation的工作工程:
当框架收到一个请求时,她首先必须决定这个URL指向了哪个动作Action。
这个Action的一个实例会被加入到一个新创建的ActionInvocation实例中。
接着ActionInvocation会询问配置文件,确定需要什么拦截器,以及以什么样的顺序触发他们。
随后这些拦截器也会被加入ActionInvocation中。
struts内部拦截器:
工具拦截器:timer(时间拦截器),logger(简单日志记录)
数据转移拦截器:params(将参数转移到ValueStack上,defaultStack)
static-params(将xml配置文件的设置参数转移到ValueStack,defaultStack)并在params之前
fileUpload(将文件和元数据装换为常规请求参数,defaultStack)
autowirting(Spring相关)
servlet-config(将Servlet对象注入action的方法,defaultStack)
-
-
-
- ServletContextAware设置ServletContext
- ServletRequestAware设置ServletRequest
- ServletResponseAware设置ServletResponse
- ParameterAware设置Map类型请求参数
- RequestAware设置Map类型的请求属性
- SessionAware设置Map类型的会话属性
- ApplicationAware设置Map类型的应用程序领域属性
- PrincipalAware设置Principal对象(安全相关)
-
-
工具流拦截器:workflow(数据验证等,defaultStack)
vaildation(数据验证,defaultStack)
prepare(追加额外处理,defaultStack)
modeldriven(老朋友了,将对象放在ValueStack请求参数,defaultStack)
其他拦截器:exception(defaultStack),token,token-session,scoped-modeldriven(defaultStack),execAndWait
自定义拦截器:
编写自定义拦截器时需要实现Interceptor接口,这里接口下只有三个方法
void destroy(); void init(); String intercept(ActionInvocation invocation)throws Exception;
前两个时典型的生命周期函数,真正的业务逻辑发生在intercept()中
AuthenticationInterceptor.java
public String intercept( ActionInvocation actionInvocation ) throws Exception { Object userToken = session.get( Struts2PortfolioConstants.USER ); if ( !( userToken instanceof User ) ) session.remove (Struts2PortfolioConstants.USER ) ; User user = (User) session.get( Struts2PortfolioConstants.USER ); if (user == null) { return Action.LOGIN; } else { Action action = ( Action ) actionInvocation.getAction(); if (action instanceof UserAware) { ((UserAware)action).setUser(user); } System.out.println("Logged in: interceptor"); return actionInvocation.invoke(); } }
struts.xml <interceptors> <interceptor name="authenticationInterceptor" class="book.four.utils.AuthenticationInterceptor" /> <interceptor-stack name="secureStack"> <interceptor-ref name="authenticationInterceptor" /> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="secureStack" /> <global-results> <result name="login" type="redirect"> /bookFour/LoginForm.action </result> <result name="error">/bookFour/Error.jsp</result> </global-results>
上面的代码片段节选自书中的源代码,action instanceof UserAware看起来怪怪的,Struts2PortfolioConstants.USER是一个常量“User”
说明:
我们可以看到AuthenticationInterceptor在获得usertoken为空时直接返回一个自己的Result字段,这个字段在xml文件中被定义为了global-results,即全局Result,大家都可以使用而非特定的action
return actionInvocation.invoke(),递归调用通知下一个拦截器
xml中的<interceptors>中定义了一个新的拦截器栈secureStack,并把它设为了默认,它由我们自定义的authenticationInterceptor和default构成,如前文所说,使用defaultStack的前提是你的package继承了struts-default包
后记-
第四章主要就是讲拦截器的工作流程和原理,自定义了一个拦截器,唯一迷得地方就是在定义拦截器中action instanceof UserWare这一定,运行代码尝试了半天并没有发现有什么用,一直都是false。。。