同样来到请求处理的核心类DispactcherServlet,再次debug。
主要就是两个关键:一是handler 二是adapter (request->mappedHandler->handlerAdapter)最后的mv对象调用handle方法:
先是取得handler(mappedHandler),类型为HandleMethod(上一篇文章已提到过):
执行到这一行得到一个HandlerAdapter对象,也就是为前文取得的handler寻找一个适配器(adapter):(一)HandlerAdapter有四种类型:
RequestMappingHandlerAdapter见名知意,就是支持在方法上标注@RequestMapping的。
HandlerFunctionAdapter支持函数式编程。
也可以自定义handlerAdapter,但是需要通过supports方法声明可用:
debug进入supports方法的具体实现:
只要handler是HandlerMethod的实例(类型),都可以将handler与adapter配合。而我们的handler在前面已经evaluate过可以看出是HandlerMethod的类型。
可见,默认匹配的adapter是RequestMappingHandlerAdapter类型的。
// actually avoke the handler
将处理过的request,response和handler都传入handlerAdapter的handle方法中,才真正启动handler。
而先进入mappedHandler.getHandler()方法取得handler(前文已有介绍不再赘述)。
再forceInto 这个handle方法:
(二)执行核心方法。
如果是RequestMappingHandlerAdapter类型的话,对应handle方法中核心调用的是RequestMappingHandlerAdapter类的handleInternal方法:
进入handlerInternal方法:
mav = this.invokeHandlerMethod(request, response, handlerMethod); //执行目标方法
进入invokeHandleMethod核心方法:
(三)参数解析器(XxxMethodArgumentResolvers)
从名字上可以看出来,对应的是@RequestParam,@PathVariable,@MatrixVariable,@RequestHeader......
先要判断是否支持当前这种参数。只有supportsParameter为true才可以继续调用参数解析器:
(四)返回值处理器(HandlerMethodReturnValueHandler)
参照(三)参数解析器的思路易知同样地得到HandlerMethodReturnValueHandler:
参数解析器是对应不同的方法参数,而返回值处理器是对应不同的返回值。
封装好这些对应的解析器和处理器后的invocableMethod再调用invokeAndHandle方法:
forceInto:
回顾一下我们对应的controller的请求方法:也在该方法首行打下断点,
在首行两句打下断点,通过放行首行判断哪一行的方法才是真正执行controller请求方法的。
通过调试发现invokeForRequest方法才是核心的执行方法:
他在这个类中。
进入invokeForRequest方法中:
getMethodArgumentValues获取方法参数值:
因为parameter是已经被封装好的包含参数类型等的参数名信息。
首先根据getMethodParameters方法得到controller方法的参数parameters,然后根据providedArgs(就是方法头的形参)和findProvidedArgument方法得到每一个位置i的参数值,存入args数组中:
如果进入getMethodArgumentValues方法一步步debug,会发现就是这样一个一个值取得然后存入args数组中的。(当然,如果一开始获得的参数列表parameters为空,那就不必再继续下去了)
(1)解析器要先判断是否支持该类型的参数,this.resolvers.supportsParameter方法实现
进入supportsParameter方法:
其实就是迭代列表逐个匹配解析器,直到找到合适的resolver。
var3是所有argumentResolvers的值的一个迭代器。
最后getArgumentResolver方法得到匹配的resolver,这里是PathVariable类型的:
然后才能进行下一步的参数解析:
(2)核心的解析参数值的方法——this.resolvers.resolveArgument
走else的逻辑,调用另一个resolveArgument方法:
查看resolveName方法:
每解析到一个参数后,都会回到RequestMappingHandlerAdapter中更新我们的请求,更新完成:
至此,已经完成在springboot中处理请求——解析controller方法参数部分的源码简析。
(ps...读源码真的好痛苦)