Spring MVC : 控制器方法处理请求的过程分析 - 3. 控制器方法参数值绑定 HandlerMethodArgumentResolver

深入探讨Spring MVC中HandlerMethodArgumentResolver的角色与工作流程,解析如何从请求中获取并转换参数,适配控制器方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本系列文章的上一篇 : Spring MVC : 控制器方法处理请求的过程分析 - 2. 请求参数的获取

在本系列文章的上一篇中,我们分析了请求参数获取的主流程。经过该主流程,从请求上下文中分析出了控制器方法执行所需的参数值列表,但该过程中非常关键的一个环节,也就是通过this.resolvers解析每个参数值的详情,我们并没有展开,到目前来讲,这一步对我们来讲仍然是黑盒子。在这篇文章中,我们就详细分析这一步骤。

提到通过this.resolvers解析参数,我们绕不开接口HandlerMethodArgumentResolver。该接口是控制器方法参数解析器的概念建模接口。该接口定义了两个方法,分别定义了一个控制器方法参数解析器所要具备的两个核心能力:

  • boolean supportsParameter(MethodParameter parameter)

    告诉调用者自己是否支持该参数的解析。该方法的实现通常基于参数的特征来声明自己是否支持。这些特征比如是参数的注解或者类型。调用者如果想使用某个HandlerMethodArgumentResolver对象解析参数,通常需要先调用方法supportsParameter检测它是否支持解析该参数。

    supportsParameter接收1个参数 :

    • parameter – 表示要被检测是否支持的目标方法参数
      通过parameter,可以获得该参数在参数列表中的索引位置,类型,该参数上的各种注解信息等等。
  • Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory)

    解析指定参数的参数值。通常调用者首先调用某个HandlerMethodArgumentResolver对象的方法supportsParameter询问它是否可解析该参数,如果可以的话,然后调用其方法resolveArgument尝试解析参数值。我们知道,来自请求的信息都是字节形式存在的,即使通过指定的字符集转换成了字符串,然后通过类似request.getParameterValues这样的方法获取得到参数值,此时参数值也是字符串或者字符串数组类型的,而通过方法HandlerMethodArgumentResolver#resolveArgument的解析,我们得到的参数值将会是已经被翻译成目标参数类型了。这也正是我们可以把这一步骤叫做"参数值绑定"的原因。

    resolveArgument方法接收4个参数 :

    • parameter – 将要解析参数值的目标方法参数信息:参数索引,参数类型,参数注解(名称,缺省值,是否必要)等信息都包含在这里
    • mavContainer – 解析过程逻辑会做一些决定,这些决定信息记录在该对象中
    • webRequest – 当前用户请求及相关信息,也就是解析参数值的请求上下文
    • binderFactory – 用于生成数据绑定器的工厂对象,一个数据绑定器用于将某个值从一个源类型转换成一个目标类型

    从方法resolveArgument的签名我们不难推断,它会针对parameter从请求上下文webRequest分析出参数值,使用binderFactory生成的数据绑定器进行类型转换,最终返回类型匹配可直接应用的参数值。-- 事实上正是如此,我们继续分析。

ServletInvocableHandlerMethod/InvocableHandlerMethod的实例成员属性resolvers类型为HandlerMethodArgumentResolverComposite它就实现了接口HandlerMethodArgumentResolver,具备HandlerMethodArgumentResolver约定的方法参数解析的能力。但实际上,HandlerMethodArgumentResolverComposite并不自己解析参数,它只是组合模式的一个应用,它组合了多个HandlerMethodArgumentResolver,当有任务到达时,HandlerMethodArgumentResolverComposite会将任务继续委托所组合的某个HandlerMethodArgumentResolver来完成。

了解完HandlerMethodArgumentResolverComposite的工作原理之后,我们需要继续了解每个真正执行参数解析和绑定任务的HandlerMethodArgumentResolver是如何工作的,因为只有了解它们的工作原理,我们才算全面掌握控制器方法参数值解析和绑定这一过程。

但通过一篇文章讲解所有HandlerMethodArgumentResolver实现类并不现实,因为Spring Web/Web MVC内置实现了二十多个HandlerMethodArgumentResolver类,分别负责从请求上下文中的各个方面解析和绑定参数值。所以本文这里不再详细展开,具体每个HandlerMethodArgumentResolver实现类是如何工作的,可以阅读如下文章 :

读到这里,你可能会有这样一个问题 :仅仅是一个参数解析器,为什么Spring会提供这么多实现类呢 ?这里,我们必须要分析一下对"参数"这一概念的理解了。通过该分析,你应该会明白Spring为什么要这么做。

一般意义上我们所说的请求参数,通常是如下几类 :

  • GET请求时,URL QueryString中传递的参数
  • POST请求时,通过表单传递的参数
  • 通过URL传递路径变量

以上参数,可以认为是狭义上的请求参数。但广义上来讲,跟当前请求相关的信息中可变的部分,比如URL ,QueryString,请求头部,会话,Cookie,甚至请求体(request body,request payload)都可以作为参数的来源,不仅如此,参数也可以不仅仅是简单数据类型,也可以是结构化的,比如JSON格式,矩阵格式等等,这个层面的参数概念,可以理解成广义的请求参数。正是因此,Spring Web才提供了各种类型的HandlerMethodArgumentResolver实现类来支持这些多种多样的请求参数的解析。而至于Spring Web/Web MVC提供了多少HandlerMethodArgumentResolver实现类,可以参考文章:Spring MVC : 框架缺省的控制器方法参数解析器

总结 :

  1. Spring Web 从请求上下文中获取参数值到目标控制器方法的绑定是通过HandlerMethodArgumentResolver来完成的。
  2. 一个HandlerMethodArgumentResolver解析请求参数主要完成以下任务 :
    1. 从请求上下文中获取参数值,通常是字符串类型,或是null;
    2. 根据目标方法上对该请求参数的缺省值信息确定是否要应用缺省值;
    3. 结合参数值和参数必要性定义做相应的逻辑处理;
    4. 绑定 : 将通常源类型为字符串的参数值转换成目标控制器方法参数类型的参数值;
  3. Spring Web 提供了多种HandlerMethodArgumentResolver实现类来解析和绑定各种类型的请求参数。

本系列文章链接合集 :

  1. 概述
  2. 执行信息记录对象ModelAndViewContainer的准备
  3. 请求参数的获取
  4. 控制器方法参数值绑定 HandlerMethodArgumentResolver
  5. 控制器方法参数值的验证 MethodValidationInterceptor
  6. 调用控制器方法本身
  7. 控制器方法返回值处理
  8. 包装返回结果 : 从ModelAndViewContainer对象构造ModelAndView对象

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值