拦截器的使用
1、拦截器的使用时机
SpringMVC中提供了一个拦截器Interceptor,其功能类似于Servlet中的过滤器Filter,但是拦截器只能拦截请求,并不能拦截响应。常用拦截器进行用户的权限验证,以及判断用户是否登录系统,未登录的进行拦截等。当你需要对用户的某些请求进行拦截时,比如非法请求,那么就可以使用拦截器来实现。
2、拦截器的原理
SpringMVC中提供了拦截器HandlerInterceptor的接口,先看这个接口源码。
org.springframework.web.servlet.HandlerInterceptor接口的源码:
只提供了3个方法:preHandle、postHandle、afterCompletion。这三个方法的说明如下:
-
preHandle方法:该方法会在控制器方法之前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。
-
postHandle方法:该方法会在控制器方法调用之后,并且在解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
-
afterCompletion方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
图示:
如果配置了拦截器,那么一个请求到达服务端之后,服务端会先执行拦截器的preHandle方法,然后执行控制器中的业务方法,然后执行拦截器的postHandle方法,然后再执行视图渲染操作,渲染完毕返回视图之后,最后执行拦截器的afterCompletion方法。
3、拦截器的使用
要想使用SpringMVC提供的拦截器,一般做法是定义一个类直接实现HandlerInterceptor接口,或者是直接继承HandlerInterceptor接口的实现类。这里就直接实现接口了。
/*
* 这个类作为拦截器使用
*/
public class MyInterceptor implements HandlerInterceptor {
// 这个方法在视图渲染之后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("执行afterCompletion方法!");
}
// 这个方法在控制器业务方法执行之后且渲染视图之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("执行postHandle方法!");
}
// 这个方法在控制器业务方法执行前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("执行preHandle方法!");
return true;
}
}
然后需要在springMVC配置文件中配置这个拦截器:
控制器:
测试:
从控制台输出可以看到执行顺序。然后再定义一个拦截器:
/*
* 这个类作为拦截器使用
*/
public class MyInterceptor2 implements HandlerInterceptor {
// 这个方法在视图渲染之后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("执行afterCompletion222方法!");
}
// 这个方法在控制器业务方法执行之后且渲染视图之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("执行postHandle222方法!");
}
// 这个方法在控制器业务方法执行前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("执行preHandle222方法!");
return true;
}
}
修改之前的拦截器:
配置拦截器:
测试:
可以看到如果先执行拦截器1的preHandle方法再执行拦截器2的preHandle方法,那么就会先执行拦截器2的postHandle方法再执行拦截器1的,先执行拦截2的afterCompletion方法再执行拦截器1的,配置多个拦截器时注意各个拦截器方法的执行顺序,这点很重要。
4、测试拦截器Intercaptor和过滤器Filter
使用SpringMVC提供的拦截器Intercaptor和Servlet提供的过滤器Filter都可以对用户的请求进行拦截处理,下面测试一下如果同时配置了Filter和Interceptor的话,执行顺序是怎样的。
定义一个过滤器:
public class MyFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化!");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("过滤器进行过滤......");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("过滤器销毁!");
}
}
配置过滤器:
测试:
结论:过滤器在web应用启动时完成初始化,启动之后,用户请求先经过过滤器Filter进行过滤,然后再经过拦截器Interceptor。