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; }
自然而然出现的HandlerIntercetor,这是用到多态的只是,超类可以调用子类方法,从而实现解耦以及拓展性。
处理完preHandle后,就到了执行控制层的方法,处理完之后先进行对view的处理,当view为空时,设置默认view,然后就执行控制层执行之后的方法,也就是postHandle
this.applyDefaultViewName(request, err); mappedHandler.applyPostHandle(processedRequest, response, err);
接着调用postHandle的调用过程也preHandle方法相似,最后使用processDispatchResult方法处理前面返回的结果,其中包括处理异常,渲染页面,触发Interceptor的afterCompletion方法。
自此我们已经彻底分析完源码当中关于拦截器的代码,在现实当中,经常用的更是自定义拦截器,主要作于于:
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView:如Hibernate,在进入处理器打开Session,在完成后关闭Session。
…………本质也是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。
自定义拦截器需要继承或者实现HandlerInterceptorAdapter类,在此贴出记录时间的代码
public class StopWatchHandlerInterceptor extends HandlerInterceptorAdapter{ private static Logger logger = Logger.getLogger(StopWatchHandlerInterceptor.class); private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long startTime = System.currentTimeMillis(); startTimeThreadLocal.set(startTime); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { long endTime = System.currentTimeMillis(); long startTime = startTimeThreadLocal.get(); String uri = request.getRequestURI(); logger.info("handle uri:" + uri + " for " + (endTime - startTime) + " ms."); } }
在dispacher的配置文件加上
<!-- 全局拦截器 -->
<mvc:interceptors>
<!--拦截所有请求-->
<bean class="scau.zzf.interceptor.interceptor.StopWatchHandlerInterceptor"/>
<mvc:interceptors/>
SpringMVC+MyBatis集成配置