Spring MVC攔截器實現分析__Spring

來源:互聯網
上載者:User

一、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可以使用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);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.