1.概念
java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截然后再之前或者之后加入某些操作。
目前,我们需要掌握的主要是Spring的拦截器,Struts2的拦截器不用深究,知道即可。
2.Spring拦截器
spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor。
2.1 HandlerInterceptor
public interface HandlerInterceptor { boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception; void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception; }
HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。
使用HandlerInterceptor步骤:
- 实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。
- 在springMVC配置文件中配置拦截器
代码实例:
public class HandlerInterceptorDemo implements HandlerInterceptor { @Override public boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o) throws Exception { System.out.println("--------HandlerInterceptor.preHandle---------"); return true; } @Override public void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("--------HandlerInterceptor.postHandle---------"); } @Override public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("--------HandlerInterceptor.afterCompletion---------"); } }
<mvc:interceptors> <!-- 在这里配置拦截器将对所有请求都拦截,公共拦截器可以有多个 --> <mvc:interceptor> <!-- 对/test进行拦截 --> <mvc:mapping path="/test"/> <!-- 特定请求的拦截器只能有一个 --> <bean class="com.xzh.HandlerInterceptorDemo" /> </mvc:interceptor> </mvc:interceptors>
测试结果:
2.2 MethodInterceptor
public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation var1) throws Throwable; }
MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。
使用MethodInterceptor步骤:
- 实现MethodInterceptor接口,或利用AspectJ的注解
- 在spring配置文件中配置
代码实例:
@Component public class MethodInterceptorDemo implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("-------MethodInterceptorDemo.invoke--------"); Method method = methodInvocation.getMethod(); System.out.println("-------method:"+ method.getName() + "-------"); return methodInvocation.proceed();//该方法不调用,则被拦截的方法不会被执行 } }
<aop:config> <!--切入点--> <aop:pointcut id="methodPoint" expression="execution(* com.xzh.*Controller.*(..)) "/><!--在该切入点使用自定义拦截器--> <aop:advisor pointcut-ref="methodPoint" advice-ref="methodInterceptorDemo"/> </aop:config>
测试结果:
3.拦截器与过滤器区别
- filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,而interceptor则基于java本身的反射机制,这是两者最本质的区别。
- 过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。
- Filter的过滤范围比Interceptor大,Filter除了过滤请求外通过通配符可以保护页面,图片,文件等等,而Interceptor只能过滤请求。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的:
最后看一下《Spring源码深度解析》对拦截器和过滤器的区别描述:
参考:
Java三大器之拦截器(Interceptor)的实现原理及代码示例