在本文末,我搜集了一些自己使用过程中的一些疑惑进行解惑,希望也一样能帮助你豁然开朗。
get请求如何传值数组、集合(List)
如题的这个case太常见了有木有,我们经常会遇到使用get请求向后端需要传值的需求(比如根据ids批量查询)。但到底如何传,URL怎么写,应该是有傻傻分不清楚的不确定的情况。
@PathVariable传参
@ResponseBody @GetMapping("/test/{objects}") public Object test(@PathVariable List<Object> objects) { System.out.println(objects); return objects; }
请求URL:/test/fsx,fsx,fsx
。控制台打印:
[fsx, fsx, fsx]
集合接收成功(使用@PathVariable Object[] objects也是可以正常接收的)。
使用时应注意如下两点:
- 多个值只能使用,号分隔才行(否则会被当作一个值,放进数组/集合里,不会报错)
- @PathVariable注解是必须的。否则会交给ServletModelAttributeMethodProcessor兜底去处理,它要求有空构造所以反射创建实例会报错(数组/List)。(注意:如果是这样写ArrayList<Object> objects,那是不会报错的,只是值肯定是封装不进来的,一个空对象而已)
说明:为何逗号分隔的String类型默认就能转化为数组,集合。请参考StringToCollectionConverter/StringToArrayConverter这种内置的GenericConverter通用转换器~~
@RequestParam传参
@ResponseBody @GetMapping("/test") public Object test(@RequestParam List<Object> objects) { System.out.println(objects); return objects; }
请求URL:/test/?objects=1,2,3
。控制台打印:
[1, 2, 3]
请求URL改为:/test/?objects=1&objects=2&objects=3
。控制台打印:
[1, 2, 3]
两个请求的URL不一样,但都能正确的达到效果。(@RequestParam Object[] objects
这么写两种URL也能正常封装)
对此有如下这个细节你必须得注意:对于集合List
而言@RequestParam
注解是必须存在的,否则报错如下(因为交给兜底处理了):
但如果你这么写String[] objects,即使不写注解,也能够正常完成正确封装。
说明:Object[] objects这么写的话不写注解是不行的(报错如上)。至于原因,各位小伙伴可以自行思考,没想明白的话可以给我留言(建议小伙伴一定要弄明白缘由)~
PS:需要注意的是,Spring MVC的这么多HandlerMethodArgumentResolver它的解析是有顺序的:如果多个HandlerMethodArgumentResolver都可以解析某一种类型,以顺序在前面的先解析(后面的就不会再执行解析了)。
源码参考处:HandlerMethodArgumentResolverComposite.getArgumentResolver(MethodParameter parameter);
由于RequestParamMethodArgumentResolver同样可以对Multipart文件上传进行解析,并且默认顺序在RequestPartMethodArgumentResolver之前,所以如果不添加@RequestPart注解,Multipart类型的参数会被RequestParamMethodArgumentResolver解析。
总结
本文是你理解Spring MVC强大的自动数据封装功能非常重要的一篇文章。它介绍了HandlerMethodArgumentResolver的功能和基本使用,以及深入介绍了最为重要的两个注解@PathVariable和@RequestParam以及各自对应的ArgumentResolver处理器。
由于这个体系庞大,所以我会分多个章节进行描述,欢迎订阅和持续关注~