sss读前必看:通过Web开发相关原理那篇文章我们知道,请求映射原理是:DispatcherServlet调用父类中的doGet和doPost,而这两个方法的核心方法是processRequest(request, response) ,而这个方法的核心方法是一个抽象方法doService(request, response),并未做具体实现,而DispatcherServlet实现了这个方法,并且其中最核心的方法是 doDispatch(request, response),因此我们通过deBug方式在doDispatch处打断点学习具体的参数处理是如何工作的。(我们调用的是getCar()方法相应的请求)
- 参数处理原理
- ①、请求DispatcherServlet
- ②③、通过请求返回处理器执行链
- ④、 HandlerAdapter - 为当前Handler (其实是通过处理器执行链中找到的处理器)找一个适配器
- ⑤⑥⑦、 适配器执行目标方法并确定方法参数的每一个值
- ①、argumentResolvers 参数解析器 ②、returnValueHandlers 返回值处理器:
- ③、执行目标方法:
- ③/1、获取方法参数的第一步:先得到所有参数对应的注解以及参数类型
- ③/2、获取方法参数的第二步:根据每个参数的注解和类型获取解析器,并得利用获得的参数解析器解析得到参数值
- ⑧、ModelAndView返回后,后续的内容就先不更新啦~
sss1 打断点:DispatcherServlet ==> doDispatch()
sss2 HandlerMapping - 找到能处理请求的处理器执行链,也就是HandlerExecutionChain(对应相应的Controller.method())
sdsss【注1】:怎么找呢?通过处理器映射器HandlerMapping进行寻找,而我们一共有五个处理器映射器放在HandlerMappings中,所以通过迭代器(老版本用的for循环)寻找哪个处理器映射器中对有相应的处理器执行链HandlerExecutionChain,然后返回相应的处理器执行链。
sdsss【注2】:RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。 所有的请求映射都在HandlerMapping中。
sdsss1. SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
sdsss2. SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
sdsss3. 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
sdsdsdsss• 如果有就找到这个请求对应的handler
sddsdssss• 如果没有就是下一个 HandlerMapping
sdsss4. 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义HandlerMapping
sdsss到此我们可以发现,通过 mappedHandler = this.getHandler(processedRequest) 我们可以得到对应的处理器执行链HandlerExecutionChain,也就是找到了相应的Controller.method(),即getCar()方法。
sssgetHandlerAdapter(Object handler)并解析第一行代码,发现一共有四个适配器,然后通过迭代器判断当前四种 HandlerAdapter 中哪一种支持当前 handler:
sdsss[注1]:0 - 支持方法上标注@RequestMapping 1 - 支持函数式编程…
sdsss到此我们可以发现,通过 HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());我们可以得到对应的适配器:RequestMappingHandlerAdapter
sss利用找到的 适配器HandlerAdapter 真正对处理器handler进行操作,并返回相应的ModelAndView
sss mv = ha.handle(processedRequest, response, mappedHandler.getHandler()):
sss 点击进入该方法:
sss 总之:最终的执行在 RequestMappingHandlerAdapter 中的 handleInternal()方法,执行返回 ModelAndView:
ssss接下来我们重点分析: mav = this.invokeHandlerMethod(request, response, handlerMethod):其中主要的方法有四个(3个也行) :
sss方法 ① :invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
sss方法 ② :invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
sss方法源码:
public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
this.resolvers = argumentResolvers;
}
public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {
this.returnValueHandlers = returnValueHandlers;
}
sss【注 1】:
sdasdassdasdasdasddsa
sss【注 2】:
sdasdassdasdasdasddsa
sssinvocableMethod.invokeAndHandle (webRequest, mavContainer, new Object[0]);
sss方法源码:
sss获取执行方法的参数值,进入invokeForRequest()方法:
sss【注】:怎么获取执行方法的所有对应的参数值呢?通过getMethodArgumentValues(request, mavContainer, providedArgs)方法获得:
sss
sss【注1】:进入supportsParameter(MethodParameter parameter)发现核心方法是getArgumentResolver(parameter),源码:
sss到此,【注1】就完成了,接下来就是利用解析器获取参数值:
sss到此:参数就完成了绑定,然后通过循环,就给每个参数都获取了值。总之就是:遍历每个参数,找到参数解析器解析参数。下面再看一下其中的细节:



