1、拦截器的意义
假如在代码段1,代码段2,代码段3中需要调用同一段代码,我们知道把这段代码提取出来,生成一个方法,在3个代码段中只要调用这个方法即可。假如将来调用的这同一段代码发生变动,只要修改一个地方即可。
但是,假如将来代码段1,代码段2和代码段3不再调用原来的方法,而是需要调用另外一个方法。这个时候,我们需要把3个代码段程序打开进行修改,因为在3个代码段中方法调用是以硬编码的方式调用的。
为了解决这个问题,我们需要一种机制,让在3个代码段中无需以硬编码的方式调用方法,同样能实现调用这个方法的功能。
拦截器就实现了这样的一种机制。拦截器提供了更高层次的解耦,目标代码无需手动调用目标方法,而是由系统完成,从而将这种调用从代码层次上升到更高层次,从而实现更高层次的解耦。个人理解其实与依赖注入的机制相同,依赖注入是无需以硬编码的方式生成实例,而拦截器是无需以硬编码的方式调用方法。
2、拦截器与AOP的关系
拦截器与AOP是密切相关的。拦截器就是基于AOP的思想,只不过当时没有明确的提出AOP的概念而已。
在struts2中,通过在struts.xml中指定拦截器,从而可以让拦截器方法在目标方法执行之前或者执行之后自动执行,从而完成通用操作的动态插入。
3、拦截器的配置
3.1 定义拦截器的格式:
<interceptor name=”拦截器名" class=”拦截器实现类"/>
如果还需要在定义拦截器时传入参数,定义格式为:
<interceptor name=”拦截器名" class=”拦截器实现类">
<param name=”参数名”>参数值</param>
…
</interceptor>
可以把多个拦截器组合在一起,形成拦截器栈。格式为:
<interceptor-stack name=”拦截器栈名”>
<interceptor-ref name=”拦截器1”/>
<interceptor-ref name=”拦截器2”/>
…
</interceptor-stack>
系统为拦截器指定参数时有两个时机,一个是在定义拦截器时,另外一个是在使用拦截器时指定参数。
3.2 使用拦截器
一旦定义了拦截器,拦截器的拦截行为会在action的execute方法执行之前被执行(???)
3.3 配置默认拦截器
可以在一个package中指定一个且只能指定一个默认的拦截器,如果action中没有显式的指定拦截器,则默认拦截器会发生作用。但是如果在action中显式的指定了拦截器,默认的拦截器将不会发生作用。
默认拦截器的定义:
<default-interceptor-ref name=”默认拦截器名”/>
4、开发自己的拦截器
如果用户要开发自己的拦截器,需要实现Interceptor接口或者继承AbstractInterceptor基类。
public class SimpleInterceptor extends AbstractInterceptor {
private String name;
public void setName(String name){
this.name=name;
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// 取得被拦截的Action实例
LoginAction action = (LoginAction)invocation.getAction();
//打印执行开始的时间
System.out.println(name + "拦截器的动作---------"+"开始执行登录Action的时间为:"+new Date());
//执行该拦截器之后的下一个拦截器
//如果该拦截器后没有其他的拦截器,则执行action的execute方法
String result = invocation.invoke();
System.out.println(name + "拦截器的动作---------"+"执行完登录Action的时间为:"+new Date());
return result;
}
}