SpringMvc源码探秘(三)请求是怎么到达Controller的(二)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

目录

SpringMvc源码探秘(一)Tomcat启动项目时Spring做了什么
SpringMvc源码探秘(二)DispatchServlet初始化
SpringMvc源码探秘(三)请求是怎么到达Controller的(一)

前言

接上一章节,说到在doDispatch方法中的HandlerAdapter调用handler方法之前,会去遍历每个HandlerInterceptor,去调用他们的preHandle方法。

本篇文章将继续上一篇文章的地方,接着往下讲解。

正式开始

handler方法

image.png image.png 到这个方法追进去是一个接口的抽象方法,需要看一下他的实现类。 image.png 我们上面获取到的ha变量也就是HandlerAdapter的类型是RequestMappingHandlerAdapter,通过查看他的类关系,最终定位到AbstractHandlerMethodAdapter当中的handler方法。

image.png 随后handler方法的内部,调用了handleInternal对象,追进去看一下。

handlerInternal 方法

image.png 这里追进来看到又是一个抽象方法,继续看他的实现。 image.png 值得欣慰的是,这次只有一个实现方法,正好落到了RequestMappingHandlerAdapter类中,这也说明我们的定位是没有错误的。

随后大致看一下上面的方法体,刚开始创建了一个ModelAndView最后的返回结果,随后调用了checkRequest方法,按照字面意思来看是校验了一下request的正确性,后面看注释的意思是是否采用block的方式去执行invokeHandlerMethod,这个synchronize变量我看默认值是false,所以这里应该会走到else代码分支,然后就返回了结果。

image.png 把else的代码块展开后发现只有一行代码,调用了invokeHandlerMethod方法,追进去看下吧。

invokeHandlerMethod 方法

image.png 这个方法是一个具体的方法,可以直接查看,三个入参这里先说一下,前两个应该不用说,主要是最后一个,传到这里的是Controller中的具体方法的封装了,这个要清楚,所以后面如果看到invoke方法的话,不要诧异这里invoke的是什么。

image.png 方法一开始,声明了一个ServletWebRequest变量,把request和response都放入了其中,看样子是对这两个东西的一个封装,目前不知道是做什么,我们接着往下看。

image.png 这一段代码,创建了两个变量,目前不知道做什么的,接着往下看。

image.png 在这段代码里创建了SerlvetInvocableHandlerMethod,值得注意的是,调用创建方法时handlerMethod传进去了,随后给这个invocableMethod变量设置了一些属性。暂时不知道这些属性是做什么的,通过字面字面意思翻译只能看懂两个。

  1. methodArgumentResolvers > 方法参数解析器
  2. methodReturnValueHandlers > 方法返回值处理器

后两个不知道是干什么的,先跳过,接着往下看。

image.png 这段代码中,创建了一个容器对象,看这个样子是给容器对象设置了一些属性,不知道是干嘛的,可以跳过,后面遇到再看。

image.png 讲真的,这一段异步的的操作我没太看懂,我看到有个if限制住了,hasConcurrentResult,我感觉我们平时的请求不会走进这里,暂时跳过吧。

image.png 看到这里就明白了,这里去调用controller中具体方法的方法了,看他的入参是把request和容器传了进去,而且没有返回值,大概率是把返回值放到了容器中,这个方法的最后把容器传入了getModelAndView方法,这里大概率就是是做了一个容器转换ModelAndView方法了。

invokeAndHandle 方法

image.png 这个方法代码比较少,第一行代码调用InvokeForRequest方法,获得了一个返回值,看到这里大概率就知道这个方法是去调用controller的具体方法了。

随后设置了responseStatus,也就是response的状态码。

然后判断返回值是不是等于null,这里也就是调用我们controller的方法返回的返回值。

然后就去调用了返回值处理器的,去处理返回值了,这里的返回值处理器是在上一层方法中给赋值的。

invokeForRequest 方法

image.png 这个方法代码更少,通过getMethodArgumentValues方法获取到,调用cotroller方法时需要用到的入参,随后调用了doInvoke方法。

getMethodArgumentValues

image.png 这个方法主要看几个关键的地方,首先parameters是调用controller需要的形参列表。

随后遍历每一个形参通过参数解析器,解析成一个具体的值,放到args数组中,最后返回。

doInvoke方法

image.png 这里的Invoke实现就比较简单了,通过反射调用method类的invoke方法。

告一段落

到这里方法就结束了,这里总结一张图,可以看一下。 image.png

都看到这了,点个赞再走呗,宝~

结束语

写文章的目的是为了帮助自己巩固知识,写的不好或者错误的地方可以在评论区指出。如果您看了文章觉得对您有所帮助可以点个赞,如果发现有些问题产生了疑惑,或者不明白的可以评论、加我微信,一定知无不言。当然也希望和大家交个朋友,相互学习。

猜你喜欢

转载自juejin.im/post/7086910574457520158