在上一篇中說(shuō)了對(duì)DispatherServlet的理解幽邓,還差一個(gè)最重要的沒(méi)說(shuō)摇幻,就是springMVC 對(duì)請(qǐng)求的處理過(guò)程夫否。
spring-webmvc對(duì)請(qǐng)求的處理過(guò)程
之所以先說(shuō)了DispatherServlet,是因?yàn)楸仨氁私馑谋举|(zhì)是什么局待,才能了解它怎么起的作用斑响,一般我們都說(shuō)DispathcerServlet是一個(gè)調(diào)度器菱属,從它的名字我們就可以發(fā)現(xiàn)它其實(shí)就是一個(gè)servlet,所以它才可以成為接收web請(qǐng)求的入口舰罚,進(jìn)而進(jìn)行調(diào)度纽门。
在調(diào)度的過(guò)程中:
首先通過(guò)doService方法來(lái)接收請(qǐng)求,在請(qǐng)求中設(shè)置環(huán)境上下文沸停,以及web相關(guān)的配置膜毁,比如主題、國(guó)際化等信息愤钾。
第二瘟滨,就到了我們的核心doDispather方法,在該方法能颁,最先通過(guò)request對(duì)象獲取HandlerExecutionChain的對(duì)象杂瘸,如下圖,可以看到在HandlerExeutionChain中不僅包含了handler本身伙菊,也包括對(duì)于這個(gè)handler的所有的攔截器败玉,一個(gè)handler可以有多個(gè)攔截器,最終由一個(gè)handler和0個(gè)或者多個(gè)攔截器組成了一個(gè)處理請(qǐng)求的鏈條镜硕。
第三运翼,在上面的步驟中,是怎么獲取到HandlerExecutionChain對(duì)象的呢兴枯?答案如下圖血淌,是通過(guò)遍歷所有HandlerMapping,然后由HandlerMapping的getHandler方法返回一個(gè)HandlerExecutionChain對(duì)象财剖。
第四悠夯,有了HandlerExecutionChain對(duì)象后,我們其實(shí)已經(jīng)獲取到了handler躺坟,但是spring在這里又通過(guò)getHandlerAdapter遍歷所有的HandlerAdapter沦补,找到一個(gè)和這個(gè)handler想匹配的HandlerAdapter。
最后咪橙,通過(guò)調(diào)用HandlerAdapter的handle方法夕膀,來(lái)處理請(qǐng)求,在這個(gè)方法中美侦,其實(shí)也是通過(guò)調(diào)用HandlerExecutionChain對(duì)象中的handler的方法來(lái)實(shí)現(xiàn)對(duì)請(qǐng)求的處理产舞。
思考點(diǎn)
哦噗,處理一個(gè)請(qǐng)求好復(fù)雜啊音榜,搞了這么多層,倒了這么多的手捧弃,究竟是為啥呢赠叼?我想:
第一擦囊,為了上層的靈活性,之所以弄了一個(gè)HandlerAdapter嘴办,就是為了使真正處理請(qǐng)求的Handler可以是任何的javaBean瞬场,大家可以在源碼里看到,handler是一個(gè)Object對(duì)象涧郊,所以在使用spring的DispacherServlet調(diào)度器中贯被,不只是能調(diào)度Controller、Servlet妆艘,理論上可以調(diào)度任何類型彤灶。
第二,為了使設(shè)計(jì)更加符合單一職責(zé)的原則批旺,例如HandlerMapping只負(fù)責(zé)請(qǐng)求和handler的對(duì)應(yīng)關(guān)系幌陕,HandlerAdapter負(fù)責(zé)執(zhí)行Handler,HandlerExecutionChain負(fù)責(zé)加入攔截器汽煮,職責(zé)非常的明確搏熄。
第三,大家想想吧暇赤,想好了告訴我心例,多謝!