1

1.SpringMVC的执行流程

2.SpringBoot请求参数解析原理

1.SpringMVC的执行流程

上一篇博客SpringBoot请求映射原理,我们讲过SpringMVC的执行流程,为了便于学习,每次在这一系列的博客开始前,我都会附上下面这张图。

image.png

2.SpringBoot请求参数解析原理

通过上篇博客的学习,我们已经知道了SpringBoot是如何通过请求路径找到对应的执行handler的,那么这篇博客,我们将学习springBoot是如何将请求参数和handler的参数一一对应并执行目标方法的过程。

先说一句话概括结论:SpringBoot通过不同的注解,读取对应的参数并封装。

我们在使用springBoot的时候,经常会在Controller方法上写上以下注解:

@PathVariable
@RequestParam
@RequestBody
...//等等相似的若干注解

我们以下面的controller方法为例,观察参数是如何封装的:

    @GetMapping("/test/{id}")
    public String test1(@PathVariable String id,
                        @RequestParam String age)
    {
        System.out.println(id);
        System.out.println(age);
        return "ok!";
    }

我们依旧在DispatcherServletdoDispatch方法上打上断点,打在下面这一行:

image.png

往里继续执行,我们会发现一行重要的代码,看函数名字就可以知晓,这是执行handler的代码:

image.png
继续往里执行,我们会看到很多类的初始化,(可不用详细阅读,抓住主流程即可),不过得记住一个重要的参数,参数解析器,等等会用来解析参数,我们在图上已经标出:

image.png

继续执行,我们会发现一个重要方法invokeAndHandle:
image.png

我们继续往里看:

image.png

可以得出,上面一行根据请求调用了handler的方法, 并且返回了一个参数,看来距离我们要找的代码越来越近了,我们继续往里点击。

image.png
根据名字可以得出,我们现在获取了所有参数args,并根据请求参数调用目标handler,我们看看getMethodArgumentValues()方法是如何获取参数的,这就是我们今天要说明的重点:

image.png

我们可以看到进行了如下三个步骤
1.springBoot先获取了handler上的所有形式参数
2.查看handler上的参数是否支持解析
3.若支持解析,则使用参数解析器进行解析。

this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);

接下来我们进入suopport方法,我们handler的第一个参数使用的是@PathVariable注解标注:
image.png
进入这个方法后,会遍历所有的参数解析器,找到支持当前参数的解析器,可以看到PathVariableMethodArgumentResolver很可能就是我们想到的,我们循环到这个值,并进入方法supportsParameter:
image.png
可以看出方法很简单,就是查看这个参数是否标注了PathVariable.class注解,这里我们返回true。(其它的参数解析也是同样的方式,可以自行debug)

参数解析器我们已经得到了,接下来我们看看解析参数的流程:

image.png

这里的逻辑也十分简单,大概分成了以下三步:
1.获得handler参数名字
2.根据参数名字从request里拿到参数
3.将这两个参数绑定在一起

image.png

其中,参数绑定器WebDataBinder中,有124个conversionService,名为参数转换器服务,可以将request中的字符串参数转换成当前handler参数需要的参数,如日期,整数,字符串等等。

image.png

通过这一系列的参数解析,我们就将handler参数和请求参数一一对应了起来。

最后使用反射调用handler的方法。
image.png

总结:
1.springBoot里有对应的参数解析器,用来解析Controller上用注解标注的不同参数。
2.springBoot里有若干的参数转换器,用来将请求参数转换成实体类的参数类型。


苏凌峰
73 声望38 粉丝

你的迷惑在于想得太多而书读的太少。