繼上一篇【深刻淺出spring】Spring MVC 流程解析 -- HanndlerMapping介紹了handler mapping後,本文按照【深刻淺出spring】Spring MVC 流程解析的分析流程,繼續往下分析,介紹下HandlerAdapter
相關的內容。前端
回顧下DispatcherServlet.doDispatch
的代碼:ios
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { 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; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
從源碼能夠看到,17行根據request拿到對象HandlerExecutionChain
(包含一個處理器 handler 如HandlerMethod 對象、多個 HandlerInterceptor 攔截器對象)後,就是24行根據handler獲取對應的adapter,並在44行調用適配器的handler方法(適配器設計模式能夠自行google瞭解),返回ModelAndView
。詳細看下getHandlerAdapter
這個方法:git
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); } if (ha.supports(handler)) { return ha; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
和上文handler mapping的邏輯很是相似,遍歷容器中的全部HandlerAdapter
,而後判斷是否支持適配此handler,這裏的關鍵方法supports
是接口HandlerAdapter
中的方法,具體邏輯由其實現類決定。默認的HandlerAdapter
的實現類有3種:spring
RequestMappingHandlerAdapter
沒有重寫supports
方法,即執行的是其父類AbstractHandlerMethodAdapter
的方法,代碼以下:segmentfault
public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); }
其中supportInternal
由子類RequestMappingHandlerAdapter
實現,直接返回常量true
,故能夠認爲只要handler屬於HandlerMethod
類型,就由RequestMappingHandlerAdapter
來適配。即RequestMappingHandlerAdapter
適配類型爲HandlerMethod
的處理器,對應RequestMappingHandlerMapping
。後端
RequestMappingHandlerAdapter
的處理邏輯主要由handleInternal
實現:設計模式
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
能夠看到,核心處理邏輯由方法invokeHandlerMethod
實現,這塊處理邏輯比較複雜,涉及輸入參數的解析,返回數據的處理,後面一篇文章【深刻淺出spring】Spring MVC 流程解析 -- InvocableHandlerMethod會重點講這塊。以前在問答社區發現不少spring mvc的問題都集中再這塊。session
@Override public boolean supports(Object handler) { return (handler instanceof HttpRequestHandler); }
源碼很簡單,適配類型爲HttpRequestHandler
的處理器mvc
@Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; }
處理邏輯也很簡單,直接調用HttpRequestHandler.handleRequest
方法,這裏不是經過返回數據實現和前端交互,而是直接經過改寫HttpServletResponse
實現先後端交互app
@Override public boolean supports(Object handler) { return (handler instanceof Controller); }
這裏的Controller
是一個接口,即全部實現Controller
接口的類,SimpleControllerHandlerAdapter
都適配
@Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); }
和HttpRequestHandlerAdapter
相似,直接調用Controller.handleRequest
,即具體實現類的handleRequest
方法,而後支持直接返回數據來和前端交互。handler_mapping_sample
中的SimpleUrlController
就是經過SimpleControllerHandlerAdapter
適配的