SpringMVC在执行过程中,DispatcherServlet会根据路径查找对应的HandlerMapping处理器映射器.
此时HandlerMapping处理器映射器会返回一个执行链,包括了handler处理器对象和HandlerInterceptor(拦截器)集合.
而这个HandlerInterceptor拦截器集合主要是对返回的handler进行了一系列的加强处理.大致可分为预处理.后处理和完成后处理.
其常见的应用场景:
1.权限检查:如登陆拦截,可以在预处理里面检查用户是否登陆,没有则response返回登陆页面.
2.性能检测:可以在拦截器预处理和后处理加上时间,相减得出系统执行过程时间.
3.日志记录:记录请求信息日志,以便进行信息监控,信息统计等.
4.通用行为:读取cookie将用户对象放入请求等.
本质也是 AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现
拦截器执行顺序:
异常中断的流程:
SpringMVC接口:
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
}
boolean preHandle :预处理方法,返回boolean类型,当返回值为true时,才会执行后续handler,返回值为false时,则中断流程,不在调用其他handler,用response来来响应页面.一般我们用来拦截用户是否登陆,登陆返回true继续执行,没有登陆返回false,response到登陆页面.
postHandle :后处理方法,在此方法中便可以看到handler执行后的ModelAndView(在视图渲染之前),便可以对ModelAndView在视图渲染前对模型数据进行处理或者对视图进行处理.
afterCompletion:在整个请求处理完毕之后调用该方法(视图渲染之后).上面提到的性能检测,便可以在这里记录请求的结束时间,来进行系统的性能检测.同时还可以进行一些资源的清理.
自定义拦截器:
public class MyInterceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("**********我是拦截器1的前置处理方法。");
// 这里返回true,代表放行,如果是false,流程中断,不再执行后续的Controller中的方法了
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("**********我是拦截器1的后处理方法。我看到了View:" + modelAndView.getViewName());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("**********我是拦截器1的完成后处理方法。");
}
}
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("------------------我是拦截器2的前置处理方法。");
// 这里返回true,代表放行,如果是false,流程中断,不再执行后续的Controller中的方法了
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("------------------我是拦截器2的后处理方法。我看到了View:" + modelAndView.getViewName());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("------------------我是拦截器2的完成后处理方法。");
}
}
xml中的配置:
<mvc:interceptors>
<!-- 方式1:直接在这里配置<bean> 对所有的Controller都拦截 -->
<bean class="cn.springmvc.handlerInterceptor.MyInterceptor1"/>
<!-- 方式2:通过mvc:interceptor来配置,同时可以指定要拦截的路径: -->
<mvc:interceptor>
<!-- 指定要拦截的路径,这里可以写固定路径,也可以使用Ant风格通配符,/**代表就是任意层数任意路径了 -->
<mvc:mapping path="/**"/>
<bean class="cn.springmvc.handlerInterceptor.MyInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
同时SpringMVC还提供了一个AsyncHandlerInterceptor拦截器接口,
在继承了HandlerInterceptor同时增加了一个afterConcurrentHandlingStarted方法:
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
}
afterConcurrentHandlingStarted该方法是用来处理异步请求。当Controller中有异步请求方法的时候会触发该方法。异步请求先支持preHandle、然后执行afterConcurrentHandlingStarted。异步线程完成之后执行preHandle、postHandle、afterCompletion。
SpringMVC提供了抽象类HandlerInterceptorAdapter来实现AsyncHandlerInterceptor接口,一般所使用的拦截器都会继承这个类,并重写里面的方法.
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}
@Override
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
@Override
public void afterConcurrentHandlingStarted(
HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
}
}