接口
public interface HandlerAdapter { /** * 是否能處理指定Handler * @param var1 * @return */ boolean supports(Object var1); /** * 處理Handler * @param var1 * @param var2 * @param var3 * @return * @throws Exception */ @Nullable ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; /** * 獲取資源最后一次更新時間 * @param var1 * @param var2 * @return */ long getLastModified(HttpServletRequest var1, Object var2); }
類圖
我們回到Dispatcher開始看起
DispatcherServlet
doDispatch
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
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; Exception dispatchException = null; try { /** * 如果配置了MultipartResolver 會調用 isMultipart() 方法判斷請求中是否包含文件。 * 如果請求數據中包含文件,則調用 MultipartResolver 的 resolveMultipart() * 方法對請求的數據進行解析,然后將文件數據解析成 MultipartFile * 並封裝在 MultipartHttpServletRequest (繼承了 HttpServletRequest) 對象中並返回 */ processedRequest = this.checkMultipart(request); //是否被解析 multipartRequestParsed = processedRequest != request; //通過HandlerMapping獲得 HandlerExecutionChanin如:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping //org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMappin mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { //沒獲取到拋出404異常 this.noHandlerFound(processedRequest, response); return; } //<1>返回對應能處理的HandlerAdapter 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; } //<3>真正的處理方法 返回視圖 沒有視圖則返回null mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //是否開啟異步管理器 if (asyncManager.isConcurrentHandlingStarted()) { return; } //設置默認的viewName this.applyDefaultViewName(processedRequest, mv); //后置處理 攔截器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var19) { dispatchException = var19; } //處理正常和異常的請求調用結果。 this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception var20) { //觸發異常攔截器的AfterCompletion實現 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20); } catch (Error var21) { //觸發異常攔截器的AfterCompletion實現 this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }
<1>getHandlerAdapter
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { Iterator var2 = this.handlerAdapters.iterator(); while(var2.hasNext()) { HandlerAdapter adapter = (HandlerAdapter)var2.next(); //<2>遍歷所有適配器 傳入handler 判斷判斷adapter是否能處理 if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
RequestMappingHandlerAdapter
<2>supports
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports
public final boolean supports(Object handler) { //判斷Handler是否是HandlerMethod 類型 supportsInternal是個抽象方法由子類實現 也就是RequestMappingHandlerAdapter return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler); }
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#supportsInternal
protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }
<3>handle
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //<4>調用子類的實現 抽象方法模板方法實現 return this.handleInternal(request, response, (HandlerMethod)handler); }
<4>handleInternal
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { //<5>檢查是否配置了只能處理請求 以及是否必須存在session而沒有傳 this.checkRequest(request); ModelAndView mav; //是否有配置根據session加鎖 if (this.synchronizeOnSession) { //true為如果不存在session則創建一個並返回 false不存在直接返回null HttpSession session = request.getSession(false); if (session != null) { /** * Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE); * 如果為空則返回當前session對象 當我們有需求保證一個session原子性的時候用吧 就一個加同步鎖動作 */ Object mutex = WebUtils.getSessionMutex(session); synchronized(mutex) { //<6>執行處理返回modelView mav = this.invokeHandlerMethod(request, response, handlerMethod); } } else { //<6>執行處理返回modelView mav = this.invokeHandlerMethod(request, response, handlerMethod); } } else { //<6>執行處理求返回modelView mav = this.invokeHandlerMethod(request, response, handlerMethod); } /** * 響應頭Cache-Control是通知瀏覽器緩存 * 這里主要是@SessionAttribute用法的處理 * 很少用到 也可兼容https://blog.csdn.net/qq_38737992/article/details/89763067 處理 */ if (!response.containsHeader("Cache-Control")) { if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { this.prepareResponse(response); } } return mav; }
<5>checkRequest
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
->
org.springframework.web.servlet.support.WebContentGenerator#checkRequest
protected final void checkRequest(HttpServletRequest request) throws ServletException { //獲得請求方式 String method = request.getMethod(); //判斷是否支持 我們可以通過這個支持的請求方式 if (this.supportedMethods != null && !this.supportedMethods.contains(method)) { throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods); //判斷是否配置了必須存在session } else if (this.requireSession && request.getSession(false) == null) { throw new HttpSessionRequiredException("Pre-existing session required but none found"); } }
<6>invokeHandlerMethod
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); ModelAndView var15; try { WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod); ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory); //交給ServletInvocableHandlerMethod 對象代理handlerMethod ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod); //入參綁定器 set 后續使用 if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } //返回值綁定器 if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } invocableMethod.setDataBinderFactory(binderFactory); invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); //異步超時時間 asyncWebRequest.setTimeout(this.asyncRequestTimeout); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); //設置線程池 asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); //攔截器 asyncManager.registerCallableInterceptors(this.callableInterceptors); //DeferredResult方式攔截器 asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); Object result; /** * 主要針對我們返回值是Callable 會釋放Dispatcher占用的線程 交給的taskExecutor之心你那個 但是與客戶端連接還保持 * 當拿回結果 從新走Dispatcher入口進來 這里判斷就會是true */ if (asyncManager.hasConcurrentResult()) { result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0]; asyncManager.clearConcurrentResult(); LogFormatUtils.traceDebug(this.logger, (traceOn) -> { String formatted = LogFormatUtils.formatValue(result, !traceOn); return "Resume with async result [" + formatted + "]"; }); //同時這類替換invocableMethod為ServletInvocableHandlerMethod.ConcurrentResultHandlerMethod 繼承ServletInvocableHandlerMethod invocableMethod = invocableMethod.wrapConcurrentResult(result); } //<7>執行后續請求處理 invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]); if (asyncManager.isConcurrentHandlingStarted()) { result = null; return (ModelAndView)result; } //<如果我們返回ModelAndView則會被ModelAndViewMethodReturnValueHandler 封裝到 mavContainenr 這里則根據MavContainer獲取 var15 = this.getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } return var15; }
ServletInvocableHandlerMethod
<7>invokeAndHandle
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
->
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //<7_1>執行參數綁定 執行控制器方法取回返回結果 Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs); this.setResponseStatus(webRequest); if (returnValue == null) { if (this.isRequestNotModified(webRequest) || this.getResponseStatus() != null || mavContainer.isRequestHandled()) { mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(this.getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); //必須返回值處理器 Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { //<10>通過返回值處理器進行返回值處理 this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception var6) { if (this.logger.isTraceEnabled()) { this.logger.trace(this.formatErrorForReturnValue(returnValue), var6); } throw var6; } }
<7_1>invokeForRequest
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
->
org.springframework.web.servlet.DispatcherServlet#doDispatch
->
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal
->
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
->
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle
->
org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //<8>通過綁定器綁定參數 Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs); if (this.logger.isTraceEnabled()) { this.logger.trace("Arguments: " + Arrays.toString(args)); } //<9>調用對應的controller方法 return this.doInvoke(args); }
<8>getMethodArgumentValues
org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { //獲得對應的綁定參數 MethodParameter[] parameters = this.getMethodParameters(); Object[] args = new Object[parameters.length]; for(int i = 0; i < parameters.length; ++i) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); //這里是優先獲取 @Init方法注冊的合適的綁定器 返回的類型綁定器 args[i] = this.resolveProvidedArgument(parameter, providedArgs); if (args[i] == null) { //遍歷所有參數綁定器找到合適的綁定器 if (this.argumentResolvers.supportsParameter(parameter)) { try { //解析出參數 args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception var10) { if (this.logger.isDebugEnabled()) { String message = var10.getMessage(); if (message != null && !message.contains(parameter.getExecutable().toGenericString())) { this.logger.debug(formatArgumentError(parameter, message)); } } throw var10; } } else if (args[i] == null) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } } } //返回參數 return args; }
<9>doInvoke
org.springframework.web.method.support.InvocableHandlerMethod#doInvoke
protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(this.getBridgedMethod()); try { //反射調用對應的Method方法 return this.getBridgedMethod().invoke(this.getBean(), args); } catch (IllegalArgumentException var4) { this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args); String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument"; throw new IllegalStateException(this.formatInvokeError(text, args), var4); } catch (InvocationTargetException var5) { Throwable targetException = var5.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException)targetException; } else if (targetException instanceof Error) { throw (Error)targetException; } else if (targetException instanceof Exception) { throw (Exception)targetException; } else { throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException); } } }
<10>handleReturnValue
org.springframework.web.method.support.InvocableHandlerMethod#handleReturnValue
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { //<11>根據響應值和響應參數選取合適的BindType HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } else { //寫入body 我們可以自定義綁定在寫入之前執行一些邏輯 handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } }
<11>selectHandler
org.springframework.web.method.support.InvocableHandlerMethod#selectHandler
@Nullable private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = this.isAsyncReturnValue(value, returnType); Iterator var4 = this.returnValueHandlers.iterator(); HandlerMethodReturnValueHandler handler; do { do { if (!var4.hasNext()) { return null; } handler = (HandlerMethodReturnValueHandler)var4.next(); } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)); //返回supportsReturnType 調用判斷是否能處理 } while(!handler.supportsReturnType(returnType)); return handler; }
如:RequestBody綁定器的實現
public boolean supportsReturnType(MethodParameter returnType) { return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class); }
總結
1.RequestMappingHandlerAdapter最終內部會將請求委托給ServletInvocableHandlerMethod處理
2.ServletInvocableHandlerMethod 會先經過參數綁定器獲得參數args數組
3.然后通能反射調用Controller的對應方法
4.再通過響應綁定器對不同的響應內容做處理 比如解析@ResponseBody的響應處理器