实现拦截器——编写自己的拦截器(下篇)
Struts2提供的拦截器机制大大提高了自身的灵活性,而且Struts2本 身提供的拦截器也为大家省了不少事,了解Struts2本身的拦截器也 是十分重要的一件事情.通过了解Struts2本身的拦截器可以使我们 编写出更强壮的拦截器.
使用预定义拦截器
在Struts2中使用拦截器需要将Action与拦截器(拦截器栈)关联起来,拦截器才可以发挥神奇的作用.在平时编写基于Struts的程序时我们并不关心拦截器(拦截器栈)的使用,这是因为Struts2默默的为我们定义了默认拦截器栈defaultStack,defaultStack中包含了经常使用的拦截器使得Struts2程序变得强大而又神奇.defaultStack中包含了以下拦截器:
[见附件]
拦截器-exception
-用于捕获在拦截器和Action执行中的异常信息,并根据异常类型显示不同的页面.
-创建ExceptionHolder对象,用来包装异常信息,并置入值栈中,供错误页面显示相关消息.这里要提到的是Struts2中以错误页面的方式来处理在程序执行过程中产生的异常信息,那么出现异常怎样指定错误页面呢? 别急,接着向下看.在Struts2中要处理异常信息显示错误页面,我们需要在Struts2 的配置文件中添加如下配置信息:
<global-results> <result name="error">页面</result> </global-results> <global-exception-mappings> <exception-mapping exception="异常类型" result="error"> <global-exception-mappings>
这些配置信息的添加是以配置文件中的包(package)为单位的,可以为每个包声明不同的错误页面.
拦截器-servletConfig
-如果Action实现了访问Servlet API的接口,如ServletContextAware,SessionAware等,这里就不一一列举了.
拦截器-i18n
-支持国际化的拦截器.
拦截器-chain
-记得两个Action互相传递参数和属性的情况吗?就是这个拦截器发挥的作用.就是让前一个Action中的参数在可以在下一个Action中可以使用.
拦截器-modelDriven
-某个Action实现了ModelDriven接口,通过getModel方法返回了领域模型的对象,那么modelDriven拦截器就将领域模型的对象压置值栈的栈顶,以方便设置或获得参数.
拦截器-staticParams
-将action配置中指定的参数值设置到Action实例中.如:
<action name="index" class="..."> <param name="param">...</param> <result>/pages/index.jsp</result> </action>
拦截器-params
-将请求参数的值设置到值栈中的属性中.
拦截器-conversionError
-将类型转化错误(由ActionContext中)加入到Action 的Field error中(通过addFieldError方法-接口ValidationAware中定义的方法)
拦截器-validation
-执行声明式校验
-如果Action所在的包中存在ActionName-validation.xml校验规则声明文件,则进行输入校验处理.有校验错误发生时,将错误消息加入Action中.
拦截器-workFlow
-执行编程式校验
-如果Action实现了Validateable接口,则执行编程式校验,调用其中的validate方法.
如果有校验错误消息,则终止正常流程,返回input字符串.
其它几个拦截器
在Struts2中我们最常用的就是默认的拦截器,我们在上面列举了默认拦截器栈中部分拦截器,我认为这些都是我们必须了解的,也是相当重要的,当然其中几个我没有提到,这并不意味这不重要.除去默认拦截器栈之外Struts2还定义了许多拦截器栈提供给我们使用,大家可以去Struts2-core包下找到struts-default.xml中查查看.另外还要提到timer和logger拦截器,也挺有作用的拦截器,自己去试试吧.
注意拦截器的顺序
在使用拦截器的同时也应该关心到配置拦截器时的顺序,要不然挺不让人放心的.大家可以参考一下defaultStack这个拦截器栈中拦截器的顺序,细细一想这样的顺序还是很道理的.大家可以根据拦截器执行的原理及开发时的需求细细品味一下.
模拟Struts2中的拦截器
在学习框架的同时可以适当了解一下框架的内部,自己动手来模拟一下框架中的某些功能,至于自己写好还是不好,我觉得这不是重点,重点在于What you learned. 和What you wanted.记得我在一次面试中面试管问我,能不能自己写一个ASP.NET框架,应该注意哪写方面,你自己想过这些吗?当时我就愣了,What! 我只是个小小菜鸟程序员,只是希望一点一点来,你上来就来这个啊.我晕了.然后自己就平自己的理解说了几句,估计是人家不满意,也就嗯了两句这问题也就算了.现在想起来确实平时在学习工具的同时也应该有自己的工具,也应该知道工具的应用领域,工具的构造.有些时候自己拿着钝器也能上战场,虽然割不出一个口子,小样我还拍不扁你啊.
好了言归正传,现在我来模拟一下Struts2中的ModelDriven接口实现的功能,至于为什么选择ModelDriven,看完你就知道了.
想一下我们平时使用ModelDriven时的情景,某个Action实现ModelDriven接口,在getModel方法中返回模型(Model)对象,然后在设置或取值时直接就可以使用模型中的属性了,嗯就是这样了.我们现在该怎么做呢?继续向下看.
The First.
我应该有个接口,然后接口中应该有个getModel方法,使得实现这个接口的类(Action)都允诺实现getModel方法.这样我new一个接口MyModelDriven:
package lele.struts2.interceptor;
public interface MyModelDriven<T> {
T getModel();
}
这里怎里怎样让 getModel方法返回任意类型的模型(Model)对象,我使用了泛型,但在Java 1.5之前,泛型是没有的,这个问题在Struts2中怎么解决呢?没有Struts2怎么解决呢?自己试试吧.
The Second
现在我有了自己的接口,那么接下来就是某个Action实现了MyModelDriven接口并且在getModel方法中返回了模型对象,又怎样知道Action实现了MyModelDriven接口并且在getModel方法中放回了模型对象呢?事情的解决方案是这样的,要在Action实例实例化出来后,某个Action被调用之前,判断是否实现了MyModelDriven接口,如果实现了那么就执行相关工作.
到这里我理所当然的想到了Interceptor,好,马上工作:
package lele.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;
public class MyModelDrivenInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof MyModelDriven) {
if (null != ((MyModelDriven) action).getModel()) {
Object obj = ((MyModelDriven) action).getModel();
ValueStack vs = invocation.getStack();
vs.push(obj);
}
}
return invocation.invoke();
}
}
在Intercept方法中当我们判断出某个Action实现了MyModelDriven接口,那么就一定能从getModel方法中得到模型对象,当这个对象不是Null值,就把对象设置到值栈中.Invocation中提供了getStack方法来获得值栈,然后把模型对象压置栈顶.然而工作做到这还没了事,设置和取值的事现在这个MyModelDrivenInterceptor还做不了,还需要ParametersInterceptor来帮忙.那么两个拦截器的位置就需要考虑一下了.
The Last
在配置拦截器时应当把ParametersInterceptor放在前面然后才是MyModelDrivenInterceptor.大家可以思考一下这样做的目的.至于详细的部署工作和测试工作,我就不在这摆弄笔墨了.
好了,今天就和大家聊到这里了希望对Struts2中的拦截器的理解再升级一个档次.下次我们再见。
PS:大家可以联系我
Mail: wanglehappy9112@gmail.com
MSN:wang4717@live.cm
QQ: 471776739