**springMVC 拦截器的原理**
今天突然有些时间,打算把拦截器这块捋一下源码,以下就是我总结的拦截器的核心方法。当然,整个实现是离不开Spring Ioc 以及Aop 的,有兴趣的可以看看Spring的整体设计理念以及方法,阅读源码会更加轻松。
我们可以通过继承HandlerInterceptorAdapter类或者实现 HandlerInterceptor接口来添加相应的拦截器。推荐使用继承HandlerInterceptorAdapter方式来实现拦截器的功能,原因是不用实现多余的方法。
拦截器的核心类DispatcherServlet,核心方法是org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse);
其中doDispatch 方法有以下的关键核心方法:
mappedHandler = getHandler(processedRequest);//获取请求的hanlder;
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//获取所对应的适配器的对象。
mappedHandler.applyPreHandle(processedRequest, response);//判断是否存在拦截;
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
说明:这是拦截的核心所在,在执行handler前执行,是用来是否拦截的中心所在,只要一个为false,整个就不通过。这是拦截器调用如果存在多个拦截器,依次从前往后执行,其中一个返回false,那么整个拦截器链就直接返回,但是triggerAfterCompletion 依就会执行全部的拦截器链,并且是倒序执行。
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
说明:这个方法是在返回modelAndView时会调用的,通过代码可以看出,存在多个拦截器时会倒序执行,前提是mappedHandler.applyPreHandle(processedRequest, response);这个方法不能为false;
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
说明:这个方法你会发现最后的方法都会走他,不管是前面applyPreHandle 方法结果如何,还是正常走下去,或者有异常,都会走这个方法,不难发现,这个方法就是为了方便记录日这或者排查问题用的。
以上就是SpringMvc 拦截器的核心所在,具体怎么实现大家可以网上索罗一番。