SpringMVC是如何处理请求中的参数的

还在好奇SpringMVC是怎么接收请求,让控制层执行的嘛?介绍了SpringMVC的执行流程,但是在请求中肯定是需要进行参数传递的,那么在SpringMVC的核心控制器拦截到请求后,它是如何处理请求中的参数的呢?

我们同样也可以使用断点跟踪的方式来了解它是怎么处理的。

还在好奇SpringMVC是怎么接收请求,让控制层执行的嘛?的第五步中可以知道核心处理器在处理请求时是通过getMethodArgumentValues方法来处理本次请求中的参数的,所有我们直接从该方法开始跟踪了解。

key=value形式传递基本数据类型

第一步:

跟踪到getMethodArgumentValues方法。

SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的

在getMethodArgumentValues方法中会根据编写的控制层方法中的参数名称从请求中拿到对应的值,返回一个数组。

第二步:
SpringMVC是如何处理请求中的参数的

该方法中首先会拿到本次请求中的所有参数(请求的控制层方法中有几个参数parameters数组的长度就是多少)之后创建了一个Object数组,循环根据parameters数组中每一个参数的信息拿到参数值放到Object数组中。

第三步:

继续跟踪resolveArgument方法,在循环中都是通过调用该方法去拿出具体的参数信息的。

SpringMVC是如何处理请求中的参数的

注:此时resolver就是一个解析器(类似于适配器,具体作用查看第二节),因为传递请求的方式有好多种所以这里模仿适配器的作用去解析请求参数。

当通过resolver调用resolveArgument方法时也是通过抽象类实现接口具体处理类集成抽象类重写抽象类中抽象方法的形式(第一节第三步有具体介绍)。

第四步:

根据debug下面的变量找到本次resolver所代表的是哪一个解析器,再通过解析器找到所集成的抽象类:

SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的

SpringMVC是如何处理请求中的参数的

在这个抽象类中重写了HandlerMethodArgumentResolver接口中的resolveArgument方法,经过这里处理后就会拿到控制器方法中的参数名称,再调用该抽象类中的抽象方法,让具体的解析类去执行。

SpringMVC是如何处理请求中的参数的

所有我们只需要在RequestParamMethodArgumentResolver(具体的处理类)中跟踪resolveName即可

SpringMVC是如何处理请求中的参数的

此时观察debug下面的变量就会发现参数的名称已经在抽象类中拿出来了,那么它将name传到这里时怎么处理的呢?

SpringMVC是如何处理请求中的参数的

该方法走到这里就会惊奇的发现,这不就是之前使用servlet时从请求域中根据参数的名称取值嘛。

执行完之后返回到第二步,将拿到的参数值赋值给Object[] args数组,最后将数组返回到第一步的invokeForRequest方法,在invokeForRequest方法中调用doInvoke方法执行控制器方法时携带上参数。

@RequestParam注解的使用
SpringMVC是如何处理请求中的参数的

有时候我们在控制层方法定义参数的时候,方法中的形参名称和请求地址中的参数名要不一致,那么这个时候核心控制器根据执行方法中的参数名称去请求地址中取参数值的时候就会对应不上。

如何在执行方法中使用了RequestParam注解就会结果这个问题,核心控制器在解析参数的时候就会使用RequestParam注解中的参数名称,而不在使用方法中的参数名称。

@RequestBody注解传递JSON参数

在日常应用中我们也会经常向服务端传JSON数据参数,那么之前那种传统的key=value的形式传参肯定不能满足需求。针对于这种JSON格式的传参,核心控制器是如何处理的呢?

大体流程和上面传递key=value形式基本一样,不同的是解析参数时使用的是不同的解析器,所以根据上面的流程直接找到获取参数方法开始跟踪:

SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的

走到这里通过解析器取解析参数的时候就会发现和key=value形式使用的解析器不一样了。(这就是所谓了各司其职的做法,定义一个接口通过抽象类实现再让不同的类去继承抽象类实现不同的应用)。

找到对应的解析器:

SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的

在readWithMessageConverters方法中具体实现了解析JSON格式的参数。

大概说下是如何获取到JSON参数数据的:
首先会拿到参数的类型,再通过流的方式拿到传递过来的JSON数据,然后根据参数的类型将JSON数据转换为对应的数据类型。

@PathVariable注解的应用

在定义控制器请求地址时有时候也会按照Restful的风格(demo1/张三/10),这种情况核心控制器又是如何解析的呢?
SpringMVC是如何处理请求中的参数的

其大致流程和之前的几种情况一样,只不过也是解析器不同而已,所以直接从获取解析器开始断点跟踪:

SpringMVC是如何处理请求中的参数的

这时发现解析器肯定是和之前的不一样的,找到具体的解析类:
SpringMVC是如何处理请求中的参数的

当它走完具体的解析类后就会从请求域中获取出本次请求的参数,然后转为Map(Map的key就是请求地址{}中的名称,value为请求时路径中的值)返回,并根据@PathVariable注解中定义的名称作为kay从map中获取对应的value并给控制器方法的形参赋值。(这就是为什么注解中的值要和定义请求地址{}中的值必须要保持一致的原因)

这里补充一下:

参数名称到底是什么时候拿到的呢?真的是在解析的过程中在解析器中拿出来的嘛。其实不是。如果该控制器方法不是第一次请求那么参数名称在处理器映射器找到具体的执行方法时,该执行方法的所有参数其实就都已经拿到了,只不过在执行之前需要根据这些执行方法上的参数去请求中匹配对应的值。

SpringMVC是如何处理请求中的参数的
SpringMVC是如何处理请求中的参数的


公众号:沉默木头人
****:沉默木头人(ID:qq_44322555)
喜欢感兴趣长按下面二维码关注吧!

SpringMVC是如何处理请求中的参数的

原创不易,不喜勿喷,如果能够帮助到你或对你有所启发欢迎下方留言。
喜欢就开始你无情的三连击:点赞、分享、关注。这将是我写作更多有趣有益有知的好文章的动力;