@RequestParam和@GetMapping中的params对请求参数的处理是不一样的

此前一直以为下面两种声明请求参数的方式是异曲同工的,起到同样的效果

 @GetMapping(value = "/list",params = {"ids"})
    public void selByIds(List<String> ids) {
        return;
    }
 @GetMapping(value = "/list")
    public void selByIds(@RequestParam(value="ids") List<String> ids) {
        return;
    }

实际上,在请求参数为List时,我发现了一些问题。
如果在@GetMapping中声明请求参数,后端会报找不到java.util.List构造器的错误。
原来后端拿到前端请求后,会去寻找List的构造方法,试图为List创建实例。但List是什么?一个接口,自然找不到构造方法。
使用@RequestParam则传值正常。
开始看源码
发现两者进行参数解析时,使用的解析器HandlerMethodArgumentResolver是不同的

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);
	}

@RequestParam用的是RequestParamMethodArgumentResolver。
@GetMapping方式,用的是ServletModelAttributeMethodProcessor。
RequestParamMethodArgumentResolver在其父类AbstractNamedValueMethodArgumentResolver的方法resolveArgument中使用WebDataBinder将原本的Object参数转成了ArrayList对象。所以才能成功被List参数接收

WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
			try {
				arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
			}

ServletModelAttributeMethodProcessor则对List这样的引用类型的参数,使用构造器创建实例。
为什么两种方式使用的参数Resolver不一样?
其实是在HandlerMethodArgumentResolverComposite这个参数解析委托类中存着一个名为argumentResolverCache的Map,在Springboot容器初始化时就初始化好了。每个Controller方法的参数情况都对应一个MethodParameter$HandlerMethodParmeter。每次要对某方法参数进行解析时,先先使对应的HandlerMethodParmeter找到在该解析器Map中找到对应的解析器,然后进行解析。

最近比较忙,先到这,不去深究Springboot处理@RequestParam和@GetMapping的详细过程。
总之,知道它两声明请求参数时,对参数的解析方式是不一样的,之后有时间再来填坑。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值