成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解SpringMVC底層原理

原創(chuàng) 精選
開發(fā) 前端
筆者的專業(yè)是軟件技術(shù),主修Java,記得剛開始寫Web應(yīng)用的時(shí)候,都是直接寫Servlet,有多少個(gè)請(qǐng)求服務(wù)就寫多少個(gè)Servlet,于是一個(gè)系統(tǒng)中出現(xiàn)了一堆的Servlet,記得那會(huì)JSP也很流行,后來又經(jīng)歷了Struts1、Struts2,到現(xiàn)在前后端技術(shù)分離了,則更多是用SpringMVC。

作者 | 波哥

審校 | 重樓

筆者的專業(yè)是軟件技術(shù),主修Java,記得剛開始寫Web應(yīng)用的時(shí)候,都是直接寫Servlet,有多少個(gè)請(qǐng)求服務(wù)就寫多少個(gè)Servlet,于是一個(gè)系統(tǒng)中出現(xiàn)了一堆的Servlet,記得那會(huì)JSP也很流行,后來又經(jīng)歷了Struts1、Struts2,到現(xiàn)在前后端技術(shù)分離了,則更多是用SpringMVC。

隨著技術(shù)的發(fā)展,你會(huì)發(fā)現(xiàn)寫代碼變得越來越簡單,當(dāng)然這個(gè)簡單是建立在前輩大神們深邃的設(shè)計(jì)思想上的,今天我們就來詳細(xì)聊聊SpringMVC,學(xué)習(xí)SpringMVC底層原理的同時(shí),感受下大神們的設(shè)計(jì)思想。

我們先來通過一張圖了解下SpringMVC處理請(qǐng)求的整體流程:

使用過SpringMVC的老鐵們都知道,在SpringMVC中最核心的就是DispatcherServlet類,接下來筆者將從DispatcherServlet如何處理請(qǐng)求的整體流程來闡述它的底層實(shí)現(xiàn)。

DispatcherServlet毫無疑問是一個(gè)HttpServlet,因此可以追蹤到所有的請(qǐng)求都會(huì)進(jìn)入到doDispatch方法中,而這個(gè)方法就是咱們要解剖的方法:

該方法主要有幾條主線:獲取HandlerExecutionChain、獲取HandlerAdapter、調(diào)用Adapter的handle方法、視圖處理器處理。下面我們將從這幾個(gè)主線逐一分析。

一、獲取HandlerExecutionChain

首先說明下這個(gè)HandlerExecutionChain,它里面封裝了一堆的Interceptor攔截器,以及Handler,它是一個(gè)處理鏈,通過getHandler方法獲取得到:

從代碼中我看到,這里循環(huán)handlerMappings,調(diào)用HandlerMapping的getHandler方法來獲取HandlerExecutionChain對(duì)象,獲取到了就返回,那這個(gè)handlerMappings都包含了哪些HandlerMapping呢?它們是什么時(shí)候被塞到handlerMappings集合中去的?

在DispatcherServlet的initStrategies方法中,會(huì)初始化一堆的數(shù)據(jù),其中就有調(diào)用initHandlerMappings方法來初始化HandlerMapping,放到handlerMappings集合中,至于initStrategies方法是怎么被調(diào)用的,大家看下DispatcherServlet的繼承結(jié)構(gòu)圖,然后根據(jù)Servlet的生命周期跟蹤下相信就知道了。

我們來看下initHandlerMappings方法:

從方法中可以看出,從Spring的Bean工廠中獲取HandlerMapping.class類型的Bean,以得到handlerMappings,在實(shí)際過程中,和咱們實(shí)際應(yīng)用相關(guān)的HandlerMapping主要包括:BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、
RequestMappingHandlerMapping這三類,當(dāng)然還有其他。

所以我們就知道了,上面是調(diào)用這三個(gè)HandlerMapping的getHandler方法來獲取HandlerExecutionChain對(duì)象。我們大概猜想,這個(gè)getHandler方法是根據(jù)請(qǐng)求的URL路徑,來獲取到處理的對(duì)象或者方法,這個(gè)是順理成章的,因?yàn)槲覀冊陂_發(fā)的時(shí)候,就是通過配置path路徑來明確請(qǐng)求的路徑和方法或類的對(duì)應(yīng)關(guān)系的。

我們先來看它們內(nèi)部到底存放了什么,以及getHandler方法的具體邏輯,我們主要看BeanNameUrlHandlerMapping和
RequestMappingHandlerMapping。

1.BeanNameUrlHandlerMapping

從它的繼承關(guān)系圖中可以看到,它是Aware的實(shí)現(xiàn)類,跟蹤它的生命周期,Spring會(huì)調(diào)用initApplicationContext方法,然后調(diào)用detectHandlers方法來找到對(duì)應(yīng)的Handler,并調(diào)用registerHandler方法將找到的Handler添加到handlerMap這個(gè)Map集合中去。

那上面"對(duì)應(yīng)的Handler"需要滿足什么條件呢?

看上面的判斷邏輯,表明如果bean的名稱是以"/"開頭,則滿足條件,然后從Spring的Bean工廠中獲取到對(duì)應(yīng)的Bean實(shí)例,添加到handlerMap集合。

在具體使用時(shí),可以實(shí)現(xiàn)Controller和HttpRequestHandler接口,同時(shí)Component注解的value值以"/"開頭。

好,數(shù)據(jù)準(zhǔn)備完成,接下來就是getHandler方法:

跟蹤代碼可以看出,就是根據(jù)URL從handlerMap獲取到對(duì)應(yīng)的實(shí)例,隨后再將handler和HandlerInterceptor封裝成HandlerExecutionChain對(duì)象:

2.RequestMappingHandlerMapping

RequestMappingHandlerMapping是InitializingBean的實(shí)現(xiàn)類,在bean的初始化階段,它的afterPropertiesSet方法會(huì)被Spring調(diào)用,跟蹤該方法:

發(fā)現(xiàn)獲取所有的bean實(shí)例,然后循環(huán)調(diào)用processCandidateBean方法:

必須滿足一定條件的實(shí)例才會(huì)被處理,這個(gè)條件就是類上面包含Controller或者RequestMapping注解:

對(duì)于滿足上述條件的bean,會(huì)在detectHandlerMethods方法中將RequestMapping注解中的路徑和對(duì)應(yīng)的方法封裝成HandlerMethod,并添加到mappingLookup集合中。

然后調(diào)用getHandler方法,根據(jù)請(qǐng)求URL從mappingLookup集合中取出HandlerMethod,并封裝成HandlerExecutionChain對(duì)象。

二、獲取HandlerAdapter

在上述調(diào)用getHandler方法,獲取到HandlerExecutionChain對(duì)象后,接下來調(diào)用getHandlerAdapter方法獲取HandlerAdapter:

循環(huán)所有的HandlerAdapter,調(diào)用supports方法判斷HandlerAdapter是否支持處理Handler。這里有兩個(gè)問題:第一、HandlerAdapter有哪些?它們是什么時(shí)候被初始化的?第二、每個(gè)HandlerAdapter的supports方法的具體實(shí)現(xiàn);

1.HandlerAdapter有哪些?它們是什么時(shí)候被添加到handlerAdapters的?

同上,HandlerAdapter的初始化也是在initStrategies方法中發(fā)起的,在initHandlerAdapters方法中完成具體的添加:

可以看到,從Spring容器中獲取所有的HandlerAdapter類型的Bean添加到handlerAdapters中,默認(rèn)情況下包括:
RequestMappingHandlerAdapter、HandlerFunctionAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter四個(gè)實(shí)現(xiàn)類的Bean實(shí)例。

2.HandlerAdapter的supports方法的具體實(shí)現(xiàn)

我們這里主要講下
RequestMappingHandlerAdapter、SimpleControllerHandlerAdapter和HttpRequestHandlerAdapter的supports實(shí)現(xiàn)邏輯:

  • RequestMappingHandlerAdapter

Handler是HandlerMethod類型,則由RequestMappingHandlerAdapter處理。

  • SimpleControllerHandlerAdapter

如果handler是Controller的實(shí)現(xiàn)類,則會(huì)由SimpleControllerHandlerAdapter處理。

  • HttpRequestHandlerAdapter

如果handler是HttpRequestHandler的實(shí)現(xiàn)類,則會(huì)由HttpRequestHandlerAdapter處理。

三、調(diào)用HandlerAdapter的handle方法

在獲取到HandlerAdapter后,還會(huì)調(diào)用interceptor的preHandle方法,這里就不詳細(xì)描述了。這里咱們直接看HandlerAdapter的handle方法的具體實(shí)現(xiàn)。

1.RequestMappingHandlerAdapter

相對(duì)于其他Adapter的處理方法,RequestMappingHandlerAdapter要復(fù)雜的的多

顯示創(chuàng)建ServletInvocableHandlerMethod對(duì)象,然后往對(duì)象中添加HandlerMethodArgumentResolvers和HandlerMethodReturnValueHandlers,這兩個(gè)接口很重要,是SpringMVC的兩個(gè)重要擴(kuò)展點(diǎn)。

隨后開始處理,總結(jié)來說主要做了兩件事:

獲取方法參數(shù)值,然后調(diào)用方法:

執(zhí)行方法相對(duì)簡單,咱們主要來看看是如何獲取方法參數(shù)值的:

先獲取到方法上的所有參數(shù)信息MethodParameter,然后調(diào)用
resolvers.supportsParameter方法來判斷是否支持對(duì)參數(shù)類型進(jìn)行轉(zhuǎn)換,那這個(gè)resolvers是啥?它是一個(gè)HandlerMethodArgumentResolver,里面包含了一堆的HandlerMethodArgumentResolver,而這個(gè)HandlerMethodArgumentResolver就是專門負(fù)責(zé)參數(shù)轉(zhuǎn)換用的:

除了SpringMVC自己提供的HandlerMethodArgumentResolver外,還支持讓咱們自己來提供,只要實(shí)現(xiàn)HandlerMethodArgumentResolver即可。SpringMVC通過調(diào)用HandlerMethodArgumentResolver類的supportsParameter方法來找到一個(gè)適合處理的HandlerMethodArgumentResolver,找到了合適的Resolver后,調(diào)用它的resolveArgument方法來進(jìn)行參數(shù)轉(zhuǎn)換,最終得到所有的參數(shù)值。

對(duì)返回值進(jìn)行處理

在調(diào)用方法完成后,如果有返回值,則調(diào)用returnValueHandlers.handleReturnValue來處理返回值,這個(gè)returnValueHandlers是HandlerMethodReturnValueHandler類型的實(shí)例,它包含了一堆的HandlerMethodReturnValueHandler,HandlerMethodReturnValueHandler就是專門處理返回值的實(shí)現(xiàn)類,除了默認(rèn)的HandlerMethodReturnValueHandler外,SpringMVC還允許咱們自己實(shí)現(xiàn)HandlerMethodReturnValueHandler。

首先SpringMVC會(huì)獲取一個(gè)最合適的HandlerMethodReturnValueHandler:

選擇的邏輯就是循環(huán)調(diào)用所有HandlerMethodReturnValueHandler的supportsReturnType方法,返回為true的就是最合適的:

得到HandlerMethodReturnValueHandler后,調(diào)用它的handleReturnValue方法來完成返回值的處理。

2.SimpleControllerHandlerAdapter


SimpleControllerHandlerAdapter的handle方法,就是執(zhí)行Controller實(shí)現(xiàn)類的handleRequest方法。

3.HttpRequestHandlerAdapter

HttpRequestHandlerAdapter的handle方法,就是執(zhí)行HttpRequestHandler實(shí)現(xiàn)類的handleRequest方法。

四、視圖渲染

上述完成Adapter的handle方法后,會(huì)執(zhí)行過濾器HandlerInterceptor的postHandle方法,這里不再描述。如果返回值是ModelAndView,則會(huì)調(diào)用processDispatchResult,來完成視圖渲染:

這里會(huì)先得到一個(gè)View,也就是視圖器,然后調(diào)用view的render方法來完成渲染處理。那核心點(diǎn)就是如何獲取這個(gè)View。

循環(huán)調(diào)用viewResolvers中ViewResolver的resolveViewName方法,得到最合適的View。默認(rèn)情況下SpringMVC提供了四種類型的View:BeanNameViewResolver、ViewResolverComposite、
InternalResourceViewResolver、ContentNegotiatingViewResolver,當(dāng)然咱們也可以自己實(shí)現(xiàn)ViewResolver,從而添加自己的View。

以上就是SpringMVC底層的大致實(shí)現(xiàn)原理,希望能給讀者朋友們一些幫助!

作者介紹

波哥,互聯(lián)行業(yè)從業(yè)10余年,先后擔(dān)任項(xiàng)目總監(jiān)及架構(gòu)師。目前專攻技術(shù),喜歡研究技術(shù)原理。技術(shù)全面,主攻Java,精通JVM底層機(jī)制及Spring全家桶底層框架原理,熟練掌握當(dāng)前主流的中間件、服務(wù)網(wǎng)格等技術(shù)原理。


責(zé)任編輯:華軒 來源: 51CTO
相關(guān)推薦

2022-12-19 08:00:00

SpringBootWeb開發(fā)

2023-07-11 08:00:00

2023-07-17 08:02:44

ZuulIO反應(yīng)式

2021-02-20 08:40:19

HiveExplain底層

2023-07-20 10:04:37

底層路由配置

2021-08-29 07:41:48

數(shù)據(jù)HashMap底層

2021-08-31 07:36:22

LinkedListAndroid數(shù)據(jù)結(jié)構(gòu)

2019-12-16 10:01:54

Java開發(fā)Web

2020-11-05 11:14:29

Docker底層原理

2023-01-04 07:54:03

HashMap底層JDK

2024-03-07 07:47:04

代碼塊Monitor

2023-10-18 10:55:55

HashMap

2021-07-05 07:51:43

JVM底層Python

2021-07-23 13:34:50

MySQL存儲(chǔ)InnoDB

2021-01-08 08:34:09

Synchronize線程開發(fā)技術(shù)

2020-08-10 18:03:54

Cache存儲(chǔ)器CPU

2022-11-15 08:10:23

SpringMyBatis底層

2023-02-12 23:23:30

2022-11-04 09:43:05

Java線程

2022-12-14 15:34:33

架構(gòu)開發(fā)雙線程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩欧美三区 | 正在播放国产精品 | 成人在线精品视频 | 午夜黄色影院 | 日韩精品国产精品 | 一级毛片视频 | 在线看亚洲 | 亚洲91 | 亚洲视频在线看 | 91久久精品| 在线欧美亚洲 | 午夜久久久久久久久久一区二区 | 国产免费拔擦拔擦8x高清 | 黄a大片 | 成人午夜性成交 | 成人国产精品免费观看 | 久久不卡 | 在线观看毛片网站 | 久久国产精品99久久久久 | 久草成人| 亚洲成人一区 | 亚洲欧美视频 | 91在线导航 | 亚洲精品一区二区三区蜜桃久 | 久久99精品久久久久久国产越南 | 精品一区二区三区入口 | 美女操网站 | 91天堂| 97成人免费 | 成人在线视频观看 | 免费99精品国产自在在线 | 在线视频国产一区 | 奇米影视在线 | 99热这里都是精品 | 亚洲欧洲一区二区 | 在线免费观看毛片 | 色一情一乱一伦一区二区三区 | 久久高清| 视频一区在线 | 久久久久久久久久久国产 | 99精品视频免费观看 |