摘要:概述本章我們主要分析處理組件的處理流程以及其接口源碼。概括來說,使用組件分為兩步,首先是注冊組件,其次是處理用戶請求,以下針對這兩個過程進(jìn)行詳細(xì)的分析。本系列文章是基于。接下來的幾章將分析提供的適配策略,希望本節(jié)對大家能有幫助,謝謝。
概述
本章我們主要分析Spring處理HandlerAdapter組件的處理流程以及其接口源碼。概括來說,Spring使用HandlerAdapter組件分為兩步,首先是注冊組件,其次是處理用戶請求,以下針對這兩個過程進(jìn)行詳細(xì)的分析。
本系列文章是基于Spring5.0.5RELEASE。
注冊HandlerAdapter一般情況下,在使用Spring MVC時,我們會配置在應(yīng)用啟動時加載和初始化Spring MVC組件,也就是在部署描述文件中配置
/** * 初始化策略對象 */ protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); // 初始化處理器適配器HandlerAdapter initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; // 在部署描述文件中可控制該參數(shù) if (this.detectAllHandlerAdapters) { // 從應(yīng)用上下文中查找HandlerAdapter MapmatchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<>(matchingBeans.values()); // 對使用的HandlerAdapter進(jìn)行排序,spring提供的只有RequestMappingHandlerAdapter實現(xiàn)了Ordered接口,其他都不具備排序功能 AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } else { try { // 如果在部署描述文件中配置了detectAllHandlerAdapters=false,此時spring會加載名稱為handlerAdapter的bean為處理器適配器 HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); // 轉(zhuǎn)化為集合賦給handlerAdapters屬性 this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we"ll add a default HandlerAdapter later. } } // 如果未配置HandlerAdapter,注冊默認(rèn)的處理器適配器,即從DispatcherServlet.properties中獲取的HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter和ReqeustMappingHandlerAdapter if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet "" + getServletName() + "": using default"); } } }
以上就是Spring MVC對HandlerAdapter組件的注冊過程。
處理請求應(yīng)用在啟動時完成了HandlerAdapter的注冊,即具備了處理用戶請求的能力,那么在用戶發(fā)起請求時,請求會有DispatcherSerlvlet所攔截,最終調(diào)用其doDispatch方法進(jìn)行處理,源碼如下:
/** * 處理請求分發(fā)給handler */ 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 { // 附件上傳有關(guān),后續(xù)分析multipartResolver時再詳細(xì)分析 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 獲取請求處理的HandlerExecutionChain對象,該對象組裝了我們的handler和相關(guān)攔截器 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // 獲取請求處理的處理器適配器,在getHandlerAdapter方法中進(jìn)行適配策略的判斷 // 參加下面getHandlerAdapter的方法詳解 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; } } // 攔截器處理用戶請求,即執(zhí)行請求相關(guān)的攔截器方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 調(diào)用handler處理方法,由此,通過適配器模式就調(diào)用到了我們使用的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); } } } } /** * 返回handler對象的處理器適配器 */ protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { // 迭代處理器適配器策略,判斷handler是否適配成功 for (HandlerAdapter ha : this.handlerAdapters) { if (logger.isTraceEnabled()) { logger.trace("Testing handler adapter [" + ha + "]"); } // 進(jìn)行適配策略的判斷 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"); }
以上就是HandlerAdatper處理用戶請求源碼分析。
接口分析通過前面兩部分,我們分析了Spring MVC對HandlerAdapter組件的使用,包括注冊和處理請求過程,接下來我們看一下給接口的定義,源碼如下:
package org.springframework.web.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable; public interface HandlerAdapter { /** * 判斷適配器是否適配handler,適配策略由子類實現(xiàn) */ boolean supports(Object handler); /* * 使用適配的handler執(zhí)行用戶請求 */ @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /** * 返回資源的最后修改時間,如果handler實現(xiàn)類不支持可以返回-1 */ long getLastModified(HttpServletRequest request, Object handler); }
以上是HandlerAdapter接口的源碼分析,如需自定義HandlerAdapter,只需要實現(xiàn)該接口,在supports方法中定義適配策略,并實現(xiàn)handle方法進(jìn)行調(diào)用即可。
總結(jié)本文主要分析了Spring MVC使用HandlerAdapter組件處理用戶請求的過程,從過程來看,用戶可干預(yù)的也就是實現(xiàn)HanderApater接口,自定義處理器適配器。
接下來的幾章將分析Spring MVC提供的HandlerAdapter適配策略,希望本節(jié)對大家能有幫助,謝謝。
最后創(chuàng)建了qq群方便大家交流,可掃描加入,同時也可加我qq:276420284,共同學(xué)習(xí)、共同進(jìn)步,謝謝!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69547.html
摘要:本系列文章是基于。說這么多就是想解釋下什么是適配器。本節(jié)我們主要從整體以及概念上闡述了的,后續(xù)會逐個分析提供的四種適配器,希望本節(jié)對大家能有幫助,謝謝。最后創(chuàng)建了群方便大家交流,可掃描加入,同時也可加我,共同學(xué)習(xí)共同進(jìn)步,謝謝 概述 本章開始,我們分析Spring MVC的另一個重要組件,即HandlerAdapter,從命名上我即可直觀的理解為處理器適配器,那么處理器適配器是什么意思...
摘要:概述回顧上兩章,我們主要分析了的概念作業(yè)以及如何使用的組件,本節(jié)以及后續(xù)幾章,將介紹為我們提供的的具體實現(xiàn)類,基于源碼和設(shè)計層面進(jìn)行介紹,歡迎大家關(guān)注。本系列文章是基于。 概述 回顧上兩章,我們主要分析了HandlerAdapter的概念、作業(yè)以及Spring MVC如何使用的HandlerAdapter組件,本節(jié)以及后續(xù)幾章,將介紹Spring為我們提供的HandlerAdapter...
摘要:問題來了,我們到底還在用嗎答案是,不全用。后者是初始化的配置,主要是的配置。啟動類測試啟動項目后,在瀏覽器里面輸入。通過查詢已裝載的,并且支持該而獲取的。按照前面對的描述,對于而言,這個必定是。的核心在的方法中。 之前已經(jīng)分析過了Spring的IOC(《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》)與AOP(《從源碼入手,一文帶你讀懂Spring AOP面向切面編程》)的源碼,本次...
摘要:概述本章開始進(jìn)入另一重要的組件,即視圖組件,處理視圖組件使用兩個主要的接口是和。接口的作用是用于處理視圖進(jìn)行渲染。延用之前的介紹流程,本章分兩部分進(jìn)行闡述啟動初始化和請求處理。 概述 本章開始進(jìn)入另一重要的組件,即視圖組件,Spring MVC處理視圖組件使用兩個主要的接口是ViewResolver和View。根據(jù)名稱可知,ViewResolver即視圖解析器,其作用是把邏輯視圖名稱解...
摘要:處理器是繼前端控制器的后端控制器,在的控制下對具體的用戶請求進(jìn)行處理。由于涉及到具體的用戶業(yè)務(wù)請求,所以一般情況需要程序員根據(jù)業(yè)務(wù)需求開發(fā)。 1、mcv整體架構(gòu)和流程 showImg(https://segmentfault.com/img/bV55Qq?w=860&h=406); 用戶發(fā)送請求至前端控制器 DispatcherServlet DispatcherServlet 收到...
閱讀 3159·2021-09-30 09:47
閱讀 2015·2021-09-22 16:04
閱讀 2284·2021-09-22 15:44
閱讀 2542·2021-08-25 09:38
閱讀 544·2019-08-26 13:23
閱讀 1230·2019-08-26 12:20
閱讀 2815·2019-08-26 11:59
閱讀 1084·2019-08-23 18:40