Spring MVC拦截器配置及其原理分析

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

原创整理不易,转载请注明出处:Spring MVC拦截器配置及其原理分析

代码下载地址: http://www.zuidaima.com/share/1751865167973376.htm

SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。

一、Servlet Filter与Spring interceptor的执行顺序

Filter有顺序吗?我们怎么控制filter的执行顺序。通过Tomcat的代码分析,servlet在Filter执行完成后才调用,如有多个filter怎么控制执行顺序,首先会想到在web.xml配置某个参数,例如order之类的,但查找一下一番,servlet并没有这个参数。试试filter Mapping的配置的先后顺序,果然有效,原来filter的执行顺序就考filter mapping在web.xml中的顺序。

spring interceptor也是这样的执行顺序,不过interceptor多一个配置参数order通过他也可以来实现interceptor的执行顺序。很多应用场景中,执行顺序还是重要的,比如cache和transaction interceptor的执行顺序,很显然cache应该在transaction之前,这样发现命中了就不用打开事务,如果transaction在前,每次都打开事务即使cache命中,这是一个无谓东动作。

二、利用springMVC的interceptor实现页面性能监控(Filter亦可)

调优第一步,找出耗时比较长的页面进行优化。利用interceptor能轻易搞定。interceptor提供了preHandle和postHandle以及afterCompletion三个方法。preHandle调用controller具体方法之前调用,postHandle完成具体方法之后调用,afterCompletion完成对页面的render以后调用,至此整个页面渲染完成。也就是说我们在preHandle记录开始的时间,在afterCompletion记录结束的时间,就可或者整个页面生成的时间。Spring自带StopWatch工具类来实现时间跟踪,关键一点interceptor不是线程安全的。我们需要借助threadlocal来实现线程安全。

@Override public boolean preHandle(HttpServletRequest request,   HttpServletResponse response, Object handler) throws Exception {  if(usePerformance){   StopWatch stopWatch = new StopWatch(handler.toString());   stopWatchLocal.set(stopWatch);   stopWatch.start(handler.toString());  }    return true; } @Override public void afterCompletion(HttpServletRequest request,   HttpServletResponse response, Object handler, Exception ex)   throws Exception {  if(usePerformance){   StopWatch stopWatch = stopWatchLocal.get();   stopWatch.stop();   String currentPath = request.getRequestURI();   String queryString  = request.getQueryString();   queryString = queryString == null ? "":"?" + queryString;   log.info("access url path:" + currentPath + queryString +  " |time:" + stopWatch.getTotalTimeMillis());   stopWatchLocal.set(null);  } } 
 

三、SpringMVC 拦截器实现分析

SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。 

 

如果你没有使用springMVC可以使用filter来完成:

stopWatch.start(); doFilterChain(); stopWatch.stop(); 

三、SpringMVC 拦截器实现分析

SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。

HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); if (interceptors != null) {  for (int i = 0; i < interceptors.length; i++) {   HandlerInterceptor interceptor = interceptors[i]; //ha.handle是调用具体的controller在此之前执行preHandle                      if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {    triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);    return;   }   interceptorIndex = i;  } } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

完成调用之后,调用render(),最后执行afterCompletion()。

if (interceptors != null) {   for (int i = interceptors.length - 1; i >= 0; i--) {    HandlerInterceptor interceptor = interceptors[i];    interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);   }  } } catch (ModelAndViewDefiningException ex) {  logger.debug("ModelAndViewDefiningException encountered", ex);  mv = ex.getModelAndView(); } catch (Exception ex) {  Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);  mv = processHandlerException(processedRequest, response, handler, ex);  errorView = (mv != null); } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) {  render(mv, processedRequest, response);  if (errorView) {   WebUtils.clearErrorRequestAttributes(request);  } } else {  if (logger.isDebugEnabled()) {   logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +     "': assuming HandlerAdapter completed request handling");  } } // Trigger after-completion for successful outcome. triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值