Spring-MVC【源码篇】请求入参类型转换

环境:Spring Boot 2.1.5.RELEASE 对应 Springframework 5.1.7.RELEASE

回顾

Spring-MVC【源码篇】请求参数和响应结果解析 一文中,提到了 Spring MVC 在进行请求处理提供了 HandlerMethodArgumentResolver(方法参数解析器)集合HandlerMethodReturnValueHandler(返回结果值解析器)集合 分别对请求参数和返回结果进行数值操作设置(如:入参的类型转换,返回结果的类型转换)。

表单入参 和 JSON格式入参

在日常开发中,针对入参通常有两种接收方式:

  • 表单格式接收
  • JSON格式接收

在日常开发中,针对入参的处理我们可以使用注解的方式对入参格式进行类型转换。
例如:对前端的入参时间格式进行类型转换

  • 表单接收使用:@DateTimeFormat
  • JSON 格式接收使用:@JsonFormat

下面来看一下我们常用的参数类型转换注解的使用

表单类型入参:时间类型转换
在这里插入图片描述

JSON 类型入参:时间类型转换
在这里插入图片描述

针对这两种类型的入参,在 Spring MVC 中对应了不同的 Resolver(参数解析器)

表单入参对应的 Resolver 为:ServletModelAttributeMethodProcessor
JSON入参对应的 Resolver 为:RequestResponseBodyMethodProcessor

下面通过源码,分析一下这两个 Resolver 解析器是如何工作的

源码分析入口

DispatcherServlet#doDispatch 作为入口进行追踪,追到 InvocableHandlerMethod#getMethodArgumentValues 该方法。

先来看看该方法代码

public class InvocableHandlerMethod extends HandlerMethod {
   
	protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
   
        // 获取所有方法参数
        MethodParameter[] parameters = this.getMethodParameters();
        Object[] args = new Object[parameters.length];
        for(int i = 0; i < parameters.length; ++i) {
   
            // 遍历每个方法参数,并堆每个方法参数根据 Resolver 进行解析
            args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, 	this.dataBinderFactory);
        }

        return args;
    }
}

主线逻辑:
1、获取所有参数值
2、根据入参获取对应的 Resolver 进行参数解析
3、将所有参数通过 Resolver 进行处理之后,重新放入新的参数对象 args 中进行返回。

代码很直观,遍历所有的入参,然后调用 Resolvers 解析器对入参进行操作,完成之后得到解析之后的值,拼接新的参数对象 args 。然后以新的参数对象 args 作为入参进行方法调用。

HandlerMethodArgumentResolverComposite#resolveArgument 作为入口,分别对 表单入参JSON 格式入参 进行简单的源码分析。

先来看看 HandlerMethodArgumentResolverComposite#resolveArgument 代码

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
   
    @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
   

        HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
        if (resolver == null) {
   
            throw new IllegalArgumentException(
                    "Unsupported parameter type [" + parameter.getParameterType().getName() + "]." +
                            " supportsParameter should be called first.");
        }
        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    }
}

上面的代码也很简单:根据前面入参的封装对象 MethodParameter 作为参数,获取该参数对应的 Resolver (解析器),然后调用对应的 Resolver (解析器)的 resolveArgument 方法对入参进行解析。

源码分析-表单入参类型转换(以 @DateTimeFormat 为例)

表单参数解析对应的 Resolver 为:ServletModelAttributeMethodProcessor

聚焦 ServletModelAttributeMethodProcessor#resolveArgument该方法由其父类 ModelAttributeMethodProcessor#resolveArgument 实现

查看代码:ModelAttributeMethodProcessor#resolveArgument

public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
   
    @Override
    @Nullable
    public final Object resolveArgument(MethodParameter parameter
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值