posts - 64,comments - 22,trackbacks - 0

          SpringMVC的攔截器不同于Spring的攔截器,SpringMVC具有統(tǒng)一的入口DispatcherServlet,所有的請(qǐng)求都通過(guò)DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也沒(méi)有代理,同時(shí)SpringMVC管理的Controller也不有代理。

          AD:

          一、Servlet Filter與Spring interceptor的執(zhí)行順序

          Filter有順序嗎?我們?cè)趺纯刂苀ilter的執(zhí)行順序。通過(guò)Tomcat的代碼分析,servlet在Filter執(zhí)行完成后才調(diào)用,如有多個(gè)filter怎么控制執(zhí)行順序,首先會(huì)想到在web.xml配置某個(gè)參數(shù),例如order之類(lèi)的,但查找一下一番,servlet并沒(méi)有這個(gè)參數(shù)。試試filter Mapping的配置的先后順序,果然有效,原來(lái)filter的執(zhí)行順序就考filter mapping在web.xml中的順序。

          spring interceptor也是這樣的執(zhí)行順序,不過(guò)interceptor多一個(gè)配置參數(shù)order通過(guò)他也可以來(lái)實(shí)現(xiàn)interceptor的執(zhí)行順序。很多應(yīng)用場(chǎng)景中,執(zhí)行順序還是重要的,比如cache和transaction interceptor的執(zhí)行順序,很顯然cache應(yīng)該在transaction之前,這樣發(fā)現(xiàn)命中了就不用打開(kāi)事務(wù),如果transaction在前,每次都打開(kāi)事務(wù)即使cache命中,這是一個(gè)無(wú)謂東動(dòng)作。

          二、利用springMVC的interceptor實(shí)現(xiàn)頁(yè)面性能監(jiān)控(Filter亦可)

          調(diào)優(yōu)第一步,找出耗時(shí)比較長(zhǎng)的頁(yè)面進(jìn)行優(yōu)化。利用interceptor能輕易搞定。interceptor提供了preHandle和postHandle以及afterCompletion三個(gè)方法。preHandle調(diào)用controller具體方法之前調(diào)用,postHandle完成具體方法之后調(diào)用,afterCompletion完成對(duì)頁(yè)面的render以后調(diào)用,至此整個(gè)頁(yè)面渲染完成。也就是說(shuō)我們?cè)趐reHandle記錄開(kāi)始的時(shí)間,在afterCompletion記錄結(jié)束的時(shí)間,就可或者整個(gè)頁(yè)面生成的時(shí)間。Spring自帶StopWatch工具類(lèi)來(lái)實(shí)現(xiàn)時(shí)間跟蹤,關(guān)鍵一點(diǎn)interceptor不是線(xiàn)程安全的。我們需要借助threadlocal來(lái)實(shí)現(xiàn)線(xiàn)程安全。

          1. @Override 
          2.     public boolean preHandle(HttpServletRequest request, 
          3.             HttpServletResponse response, Object handler) throws Exception { 
          4.         if(usePerformance){ 
          5.             StopWatch stopWatch = new StopWatch(handler.toString()); 
          6.             stopWatchLocal.set(stopWatch); 
          7.             stopWatch.start(handler.toString()); 
          8.         } 
          9.          
          10.         return true
          11.     } 
          12.  
          13.  @Override 
          14.     public void afterCompletion(HttpServletRequest request, 
          15.             HttpServletResponse response, Object handler, Exception ex) 
          16.             throws Exception { 
          17.         if(usePerformance){ 
          18.             StopWatch stopWatch = stopWatchLocal.get(); 
          19.             stopWatch.stop(); 
          20.             String currentPath = request.getRequestURI(); 
          21.             String queryString  = request.getQueryString(); 
          22.             queryString = queryString == null ? "":"?" + queryString; 
          23.             log.info("access url path:" + currentPath + queryString +  " |time:" + stopWatch.getTotalTimeMillis()); 
          24.             stopWatchLocal.set(null); 
          25.         } 
          26.     } 

          如果你沒(méi)有使用springMVC可以使用filter來(lái)完成:

          1. stopWatch.start(); 
          2. doFilterChain(); 
          3. stopWatch.stop(); 

          三、SpringMVC 攔截器實(shí)現(xiàn)分析

          SpringMVC的攔截器不同于Spring的攔截器,SpringMVC具有統(tǒng)一的入口DispatcherServlet,所有的請(qǐng)求都通過(guò)DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也沒(méi)有代理,同時(shí)SpringMVC管理的Controller也不有代理。哪不難想到我們?cè)趫?zhí)行controller之前做某些動(dòng)作,執(zhí)行完畢做某些動(dòng)作,render完成做某些動(dòng)作。SpringMVC的攔截器對(duì)應(yīng)提供了三個(gè)preHandle,postHandle,afterCompletion方法。只需在三個(gè)方法內(nèi)寫(xiě)我們需要的邏輯就行,多了都是廢話(huà),還是代碼實(shí)在。

          1. HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); 
          2.                 if (interceptors != null) { 
          3.                     for (int i = 0; i < interceptors.length; i++) { 
          4.                         HandlerInterceptor interceptor = interceptors[i]; 
          5. //ha.handle是調(diào)用具體的controller在此之前執(zhí)行preHandle                      if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 
          6.                             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 
          7.                             return
          8.                         } 
          9.                         interceptorIndex = i; 
          10.                     } 
          11.                 } 
          12.  
          13.                 // Actually invoke the handler. 
          14.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

          完成調(diào)用之后,調(diào)用render(),最后執(zhí)行afterCompletion()。

          1. if (interceptors != null) { 
          2.                 for (int i = interceptors.length - 1; i >= 0; i--) { 
          3.                     HandlerInterceptor interceptor = interceptors[i]; 
          4.                     interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); 
          5.                 } 
          6.             } 
          7.         } 
          8.         catch (ModelAndViewDefiningException ex) { 
          9.             logger.debug("ModelAndViewDefiningException encountered", ex); 
          10.             mv = ex.getModelAndView(); 
          11.         } 
          12.         catch (Exception ex) { 
          13.             Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 
          14.             mv = processHandlerException(processedRequest, response, handler, ex); 
          15.             errorView = (mv != null); 
          16.         } 
          17.  
          18.         // Did the handler return a view to render? 
          19.         if (mv != null && !mv.wasCleared()) { 
          20.             render(mv, processedRequest, response); 
          21.             if (errorView) { 
          22.                 WebUtils.clearErrorRequestAttributes(request); 
          23.             } 
          24.         } 
          25.         else { 
          26.             if (logger.isDebugEnabled()) { 
          27.                 logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + 
          28.                         "': assuming HandlerAdapter completed request handling"); 
          29.             } 
          30.         } 
          31.  
          32.         // Trigger after-completion for successful outcome. 
          33.         triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 

            原文鏈接:http://exceptioneye.iteye.com/blog/1267248
          posted on 2011-11-22 20:25 hellxoul 閱讀(2380) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Spring2.5
          主站蜘蛛池模板: 湖南省| 连江县| 察隅县| 济阳县| 香格里拉县| 丰城市| 南和县| 潍坊市| 竹溪县| 金昌市| 泰兴市| 天门市| 项城市| 德江县| 西青区| 广平县| 奈曼旗| 和硕县| 阿拉善盟| 耒阳市| 宿迁市| 平定县| 赞皇县| 友谊县| 托克逊县| 衡水市| 丰原市| 禄丰县| 灵宝市| 蒙阴县| 南开区| 万年县| 江油市| 江都市| 乐陵市| 宾阳县| 恩平市| 隆德县| 阿合奇县| 武强县| 东丽区|