栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一文搞懂SpringMVC请求流程(源码角度)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一文搞懂SpringMVC请求流程(源码角度)

请求流程

大概先了解下springMVC的执行流程文字描述,下面将进行断点跟踪。

①用户发送请求至前端控制器DispatcherServlet。
②DispatcherServlet收到请求调用HandlerMapping处理器映射器。
③处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。④DispatcherServlet调用HandlerAdapter处理器适配器。
⑤HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
⑥Controller执行完成返回ModelAndView。
⑦HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
⑧DispatcherServlet将ModelAndView传给ViewReslover视图解析器。⑨ViewReslover解析后返回具体View。
⑩DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户。

各个组件描述:

源码分析

首先这个项目只有一个Controller,而且返回的是字符串

然后DispacherServlet类的doDisPatch()方法上打上一个断点

浏览器中访问http://localhost:8080/helloworld?name=jack

查看request的局部变量

step over直到519行,step into

进去之后调用的是自己的getHandler方法

然后方法里面并没有直接getHandler,而是调用了HandlerMapping的getHandler方法,这样做其实是为了解耦,可以发现handlerMappings的size为3,说明有三个HandlerMapping(留个印象,下面要用),而且可以发现这里通过迭代器遍历每个handlerMapping来获取handler。


step over直到669行,然后step into跟进

进去看看HandlerMapping是怎么处理的(现在到了AbstractHandlerMapping类中了)

直接step into 跟进

这里就直接step over了,可以发现initLookupPath()方法就是从request中提取uri(即/helloworld)

在82行进行step into跟进(这里真正的进行handler查找了)

继续step into 跟进,然后可以发现它是从一个map中通过urlPath(也就是前面找出的url)来获取handler的,所以可以可以猜测一下:

在客服端发起请求之前springMVC就将controller对应的url作为key,将controller作为value存入了map中,当客户端发起请求之后就拿url作为key尝试从这个map中获取value(即controller,也就是handler)


继续step over ,令人失望的是map的size为0,并没有找到handler,map本应该有一个键值对的(因为写了一个controller),但现在缺发现没有,是不是说我们的猜测是错误的呢?不急,回顾一下,前面说有三个handlerMapping,是在遍历每个进行获取handler,而这个是第一个,没找到handler就正常了吧!

所以为我们直接跳出去step out,再次回到DispacherServlert里面

发现handler是null,因此使用下一个handlerMapping进行查找Handeler

然后遍历到第二个HandlerMapping (RequestMappingHandlerMapping类型需要注意一下)

同样的操作就不再啰嗦了,直接step over之后发现找到了handler

再回到doDispatch()方法里面

找到了handler之后是不是该执行handler了,但是并没有直接在这里执行,而是找HandlerAdapter来执行,可以发现有个getHandlerAdaper方法,顾名思义就是获取执行handler的适配器

step into 进行跟进,发现有四个HandlerAdaper(可以类比下之前的三个HandlerMapping)

可以发现是通过遍历四个HandlerAdaper,判断该HandlerAdaper是否支持执行前面找到的handler

一直step over 进行遍历,当HandlerAdaper是RequestMappingHandlerAdaper时支持前面的handler(因为这个handler是RequestMappingHandlerMapping找到的,忘记了返回去看看)

再次回到doDispatch方法里面,直接step over,直到539行,适配器开始执行handler了

step into 跟进,此时来到了AbstractHandlerMethodAdapter类里面(它是HandlerAdapter接口的一个抽象实现类)

继续step into ,然后来到了RequestMappingHandler类中(因为上面的AbstractHandlerMethodAdapter是抽象类,恰好handle方法又是一个抽象方法,它需要具体的实现类来实现,而前面找到支持前面找到的handler的适配器就是RequestMappingHandler,因此执行的handle方法就是RequestMappingHandler里面的实现)

继续跟进,发现调用了invokeHandlerMethod方法,见名知意,这肯定就是在调用handler的方法了,也就是调用controller的方法了

由于调用过程比较复杂(反射)就不再跟进了,直接放行控制台打印了结果,网页上也返回了结果。说明controller确实执行了。而执行返回的结果是ModleAndView,我们使用了@ResponseBody注解,因此直接返回了字符串(当前基本上都是前后端分离开发,所以返回的都是字符串,就不需要进行视图的跳转或解析了),因此ModleAndView为null,所以就doDispatch方法的核心任务就结束也就没有用到视图解析器组件,本次请求也执行完成了。
但为了学习SpringMVC的请求流程,我们继续看看doDispatch()方法里面的后续内容:
适配器执行完handler的方法并返回一个ModelAndView(mv)之后,发现调用了processDispatchResult方法,并将返回的ModelAndView(mv)传入

进入方法体:

进入render方法

这里调用了View的render方法,而这个View(它是一个接口)就充当了ViewResolver的角色,里面定义了如何处理ModelAndView的逻辑,在此就不在深究了!

至此此次使用到的组件就有前端控制器(DispatcherServlet)、处理器映射器(HandlerMapping)、处理器适配器(HandlerAdapter)和视图解析器(ViewResolver)

再回顾一下是不是就一目了然了!

一些问题
  1. 为什么要将HandlerMapping和多个HandlerAdaper以及ViewResolver独立出去而不是直接在DispatcherServlet中处理?

答:就是为了解耦合,使得系统易于扩展,DispatcherServlet将查询Handler的任务交给HandlerMapping去处理,而HandlerMapping具体怎么找便不用DispatcherServlet去关心,它只需要结果,因此大大降低了系统的耦合度,而且HandlerMapping可以采用不同的方法去查询Handler

  1. 为什么有多个HandlerMapping和多个HandlerAdaper呢?

答:第一个问题回答了将这些功能独立出来就是为了解耦、使系统易于扩展,也说了它们可以有不同的实现方法。而HandlerMapping和HandlerAdaper只是一个接口,具体的实现还得看具体的实现类,若想要采用不同的方法去实现接口定义的功能那就要有不同的实现类,因此就存在了多个HandlerMapping和多个HandlerAdaper。
那为什么要用不同的实现方法呢?这是因为Controller有不同的实现方法,对不同方法实现的controller当然就要用不同的HandlerMapping去找,同时需要不同的HandlerAdaper去执行。
具体实现方法请参照(controller的三种实现方式)https://blog.csdn.net/chuhuai8266/article/details/100757333

欢迎指正

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/659348.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号