SpringMVC的拦截器Interceptor类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
比如:可以实现:权限控制、日志、异常记录、记录方法执行时间…
在Spring MVC中使用拦截器,需要对拦截器类进行定义和配置。一般拦截器可以通过两种方式类定义。
下面我们以实现HandlerInterceptor接口的方式来自定义拦截器类:
@Component
public class MyFirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyFirstInterceptor=====================>preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyFirstInterceptor=====================>postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyFirstInterceptor=====================>afterCompletion");
}
}
可以看出自定义的拦截器类实现了HandlerInterceptor接口,并重写了接口中的三个方法。
拦截器有3个回调方法:
preHandle: 预处理回调方法,实现处理器的预处理,第三个参数为响应的处理器返回值:true表示继续向下执行(如调用下一个拦截器);false表示中断后续操作,不会继续调用其他的拦截器和控制器类的方法执行。
postHandle: 后处理回调方法,实现处理器的后处理,在渲染视图之前,此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理。
afterCompletion: 整个请求处理完成,即在视图渲染结束之后执行,可以通过该方法进行一些资源清理,类似于trycatchfinally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器才会执行。
想要使自定义的拦截器类生效,还需要在Spring MVC的配置文件中进行配置。
我们通过
元素来配置一组拦截器,若要拦截DispatcherServlet处理的所有请求,则如下面配置:
<mvc:interceptors>
<bean class="com.it.interceptor.MyFirstInterceptor"/>
<ref bean="myFirstInterceptor"/>
mvc:interceptors>
当然,我们也可以通过
的子元素
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/interceptor"/>
<ref bean="myFirstInterceptor"/>
mvc:interceptor>
mvc:interceptors>
注意:
@Component
public class MySecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MySecondInterceptor=================>preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MySecondInterceptor==================>postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MySecondInterceptor=============>afterCompletion");
}
}
<mvc:interceptors>
<ref bean="myFirstInterceptor"/>
<ref bean="mySecondInterceptor"/>
</mvc:interceptors>
从上面能够看到,若每个拦截器的preHandle()都返回true,则preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行。
若某个拦截器的preHandle()返回了false,那么preHandle()返回false和它之前的拦截器的preHandle()都会执行,而postHandle()都不执行,返回false的拦截器之前的拦截器的afterComplation()会执行。也就是已经通过的拦截器的afterCompletion会执行。
比如:我们将第二个拦截器的preHandle方法的返回值改为false,可以看到preHandle方法都执行了,postHandle没有执行,而afterComplation只执行了第一个拦截器的。
单个拦截器,程序会首先执行拦截器类中的preHandle()方法,若该方法返回true,则继续向下执行处理器中的方法,否则中断;处理完请求之后会执行postHandle()方法,然后再通过DispatcherServlet请求处理之后,最后执行afterComplation()方法。
多个拦截器同时工作时,每个拦截器的preHandle()方法都会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行。