Struts2的拦截器
Struts2的拦截器
拦截器的概述
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个Action执行前阻止其执行。同时也是提供了一种可以提取Action中可重用的部分的方式。
谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts2中称为拦截器栈,Interceptor Stack)。拦截器链就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
下面是我对于拦截器概念的理解。
我们知道在Struts2框架里面有很多的拦截器,在拦截器里面帮我们实现了一部分功能。但在Strtus2框架里面的很多的拦截器,并不是都执行,每次只会执行一些默认的拦截器,那这些拦截器是在哪儿呢?Strtus2框架里面默认拦截器位置的是在struts2-core-2.3.24.jar包下的struts-default.xml文件中,在该文件中,我们可找到默认拦截器的配置:
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="datetime"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
问题来了,拦截器是在什么时候执行的呢?在Action对象创建之后,在Action里面的方法执行之前执行拦截器。
拦截器的实现原理
大部分时候,拦截器方法都是通过代理的方式来调用的。Struts2的拦截器实现相对简单。当请求到达Struts2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。
Struts2的拦截器是可插拔的,拦截器是AOP的一种实现。Struts2拦截器栈就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
关于对拦截器的底层实现原理,我的理解是——拦截器的底层实现原理主要有两部分:
- AOP思想:面向切面(方面)编程
在实际开发中,比如说有一个基本的功能,但我们想扩展其基本的功能,使用AOP思想,就能不修改源代码扩展功能,比如登录功能,参考下图:
- 责任链模式(设计模式中的一种):类似于过滤链
过滤链:一个请求,可以有多个过滤器进行过滤,每个过滤器只有做放行操作,才能到下一个过滤器。
责任链模式:有一组操作,有增加、修改、删除操作。执行这三个操作,首先执行增加操作,增加执行之后做类似于放行的操作,放行之后执行修改操作,修改执行之后,做类似于放行的操作,放行之后执行删除操作。
拦截器的执行流程
拦截器的执行流程可参考官网提供的图,如下:
看上面的图,还是比较空洞,所以我还是做一点点解释。要理解拦截器的执行流程,须理解下面这3点:
- 拦截器在action对象创建之后,action里面的方法执行之前执行。
- 在Struts2框架里面执行默认的拦截器,在action中不需要调用拦截器的方法,使用配置方式执行,这就是AOP思想的体现。
- 执行很多的拦截器,比如有3个拦截器,首先执行拦截器1,然后做类似放行的操作,执行拦截器2,之后做类似放行的操作,执行拦截器3,做类似放行的操作之后,之后action里面的方法。
拦截器和过滤器的区别
过滤器理论上可以过滤任意内容,如过滤jsp、过滤html、过滤图片(路径)、过滤servlet等。而拦截器是可以拦截内容,但拦截器只能拦截action。