前言:這兩天學習了代理模式,天然想到了 springmvc 的 aop 使用的就是動態代理,攔截器使用的就是 jdk 的動態代理。今天看了看源碼,記錄一下。轉載請註明出處:https://www.cnblogs.com/yuxiaole/p/9969360.htmlhtml
springMVC 的攔截器使用移步:Java Servlet 過濾器與 springmvc 攔截器的區別?web
springMVC 的全部鏈接入口都會進入 DispatcherServlet,而後在這裏面去調用真正的 Controller。而攔截器要達到的做用則是在調用 Controller 先後去作一些事情。因此如今須要看看 DispatcherServlet 的源碼。spring
DispatcherServlet 的源碼入口在 doService() 方法。mvc
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if(this.logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":""; this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } Map<String, Object> attributesSnapshot = null; if(WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); label108: while(true) { String attrName; do { if(!attrNames.hasMoreElements()) { break label108; } attrName = (String)attrNames.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if(inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { this.doDispatch(request, response); } finally { if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot); } } }
doService() 方法裏面處理了一些信息以後,調用了 doDispatch() 方法。app
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { try { ModelAndView mv = null; Object dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; mappedHandler = this.getHandler(processedRequest); if(mappedHandler == null || mappedHandler.getHandler() == null) { this.noHandlerFound(processedRequest, response); return; } HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if(isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if(this.logger.isDebugEnabled()) { this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } if(!mappedHandler.applyPreHandle(processedRequest, response)) { return; } mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if(asyncManager.isConcurrentHandlingStarted()) { return; } this.applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed", var21); } this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); } } finally { if(asyncManager.isConcurrentHandlingStarted()) { if(mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if(multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }
doDispatch() 方法中經過 this.getHandler(processedRequest); 獲取到了處理器鏈 HandlerExecutionChain mappedHandle 以後,去執行了 mappedHandler.applyPreHandle(processedRequest, response) 方法,從而執行了攔截器的 preHandle 方法,若是返回爲 false,則會調用處理器鏈的 triggerAfterCompletion 方法,而後 DispatchServlet 類中會直接 retreturn;若是返回爲 true,則繼續。async
而後調用了 HandlerAdapter 的 handler() 方法;post
而後調用了 mappedHandler.applyPostHandle(processedRequest, response, mv); 方法,從而執行了攔截器的 postHandle 方法;學習
而後調用了 this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); 方法;在 processDispatchResult() 方法裏面渲染了對應的視圖,而後調用了 mappedHandler.triggerAfterCompletion(request, response, (Exception)null); 方法,從而執行了攔截器的 afterCompletion 方法。this
processDispatchResult() 源碼以下:url
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; if(exception != null) { if(exception instanceof ModelAndViewDefiningException) { this.logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException)exception).getModelAndView(); } else { Object handler = mappedHandler != null?mappedHandler.getHandler():null; mv = this.processHandlerException(request, response, handler, exception); errorView = mv != null; } } if(mv != null && !mv.wasCleared()) { this.render(mv, request, response); if(errorView) { WebUtils.clearErrorRequestAttributes(request); } } else if(this.logger.isDebugEnabled()) { this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling"); } if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if(mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, (Exception)null); } } }
從 doDispatch() 方法這裏主要須要知道 HandlerExecutionChain mappedHandler = this.getHandler(processedRequest); 這一句調用的 getHandler() 方法,源碼以下。
getHandle() 方法裏是經過 HandlerMapping 的 getHandler 方法返回 HandlerExecutionChain 的。
從代碼中不難看出整個邏輯就是依次判斷 servlet 中的每一個 handlerMapping 是否可以匹配該請求,直到找到那個匹配的而後返回處理結果。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Iterator var2 = this.handlerMappings.iterator(); HandlerExecutionChain handler; do { if(!var2.hasNext()) { return null; } HandlerMapping hm = (HandlerMapping)var2.next(); if(this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } handler = hm.getHandler(request); } while(handler == null); return handler; }
applyPreHandle() 方法源碼以下:能夠看出是順序調用攔截器的 preHandle() 方法。preHandle 返回 false 時調用了 triggerAfterCompletion 方法。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = this.getInterceptors(); if(!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; if(!interceptor.preHandle(request, response, this.handler)) { this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; }
applyPostHandle() 方法源碼以下:能夠看出這裏是逆序調用 postHandle 方法。
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = this.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); } } }
triggerAfterCompletion() 方法源碼以下:能夠看出這裏也是逆序調用 afterCompletion 方法。
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception { HandlerInterceptor[] interceptors = this.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 var8) { logger.error("HandlerInterceptor.afterCompletion threw exception", var8); } } } }
轉載請註明出處:https://www.cnblogs.com/yuxiaole/p/9969360.html