关于 GET 请求中的数组格式

2019-08-29 11:13:15 +08:00
 DreamSpace

今天上班摸鱼摸得正起劲,前端同事发来一条消息说调我接口时报错:

接口:

    @GetMapping(value = "/getList")
    public ResponseMessage getList(IpcDeviceQuery query);

参数:

	/getList?groupIdList[]=2&groupIdList[]=3

报错:

	Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

粗略看了一下,是 GET 请求中数组格式的问题,前端同事使用的格式并不能被 Springboot 的后端接收到。

网上查了查资料,发现 GET 请求传输数组参数的方式百花齐放,各种格式都有,归纳了一下,大概以下三种格式:

哪一种格式是真正符合规范的? Spring 需要定制什么才能解析格式 2 和格式 3 的参数呢?

14380 次点击
所在节点    Java
39 条回复
mikoshu
2019-08-29 11:19:19 +08:00
get 请求传啥数组 让他直接把字符串用逗号隔开给你呗
chendy
2019-08-29 11:20:09 +08:00
url 参数本身就是多值的,只不过一般用不到:n=1,2,3,4 或者 n=1&n=2&n=3&n=4
一旦要用到复杂对象结构和数组,就直接用 POST 吧,省心省事
chendy
2019-08-29 11:20:55 +08:00
忘了说 n=1,2,3,4 或者 n=1&n=2&n=3&n=4 至少 SpringMVC 可以直接用数组和集合接
baronOvO
2019-08-29 11:20:58 +08:00
我觉得 1 楼说的对
Humorce
2019-08-29 11:21:09 +08:00
路由都不规范为什么参数格式要规范呢?
me876
2019-08-29 11:29:26 +08:00
让前端用 qs 库转换下后端能接收的格式就行,这个坑我之前也踩过。

```
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
// 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
// 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
// 'a=b,c'
```
index90
2019-08-29 11:31:14 +08:00
记得是推荐格式 1
whitev2
2019-08-29 11:31:20 +08:00
get 请求也是可以有请求体的,放请求体里

@chendy #2
ipwx
2019-08-29 11:33:14 +08:00
批量的接口为啥不用 post
DreamSpace
2019-08-29 11:44:18 +08:00
@chendy 感谢,测试了下的以逗号分隔的确可以比较方便的接受

@ipwx 因为是查询数据的接口,具有幂等性的,所以使用的是 GET
ipwx
2019-08-29 11:50:52 +08:00
@DreamSpace 我个人觉得幂等性这种概念在这个例子上不重要。首先,批量接口组合数太多,基本没有 http 层缓存的价值。其次,get 参数无法应对大量 ID 的请求,还是得上 post。那些说 get 加上 body 的做法,我觉得那比违反所谓的幂等性更糟糕。综上,我觉得该用 post
wysnylc
2019-08-29 11:57:59 +08:00
1 是正确的 2,3 是什么鬼
现在一般都转成 json &n=[1,2,3]这种形式传输
PerpetualHeng
2019-08-29 12:11:51 +08:00
我先说第一点,从来没有 url 传参上会带上"[]"这种符号,即使是数据也是第一种方式。
第二传数组一般都是搞成 json 传,后端转一下。
涉及到这种传数组的请求,数据大小可以无限制,还是用 post 吧。
Vegetable
2019-08-29 12:15:39 +08:00
DavidNineRoc
2019-08-29 12:28:19 +08:00
多年的经验
1 肯定是不行的,参数后面的会覆盖前面的值
2,3 都行,因为不写索引,会类似 js 的数组,索引会自增。
*****
说 2,3 不行的,表单字段数组类型的没用过?
代码已复制,请直接使用
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="">
<input type="text" name="tags[]" />
<input type="text" name="tags[]" />
<input type="text" name="tags[]" />
<input type="text" name="tags[]" />
<button type="submit">提交</button>
</form>
</body>
</html>
DavidNineRoc
2019-08-29 12:29:34 +08:00
之所以不行的原因,多半是因为你前端对象没有 urlencode 吧
TabGre
2019-08-29 12:34:09 +08:00
6 楼说的有道理,前端可以自己拼接成你可以解析的形式,手动或者 qs 库
Sparetire
2019-08-29 12:41:00 +08:00
都可以,事实上就 HTTP 而言并没有限制你用哪种,甚至也不需要是 key=value 这样的格式,也都是合法的,这些格式都是框架的约定而已
所以后端能处理哪种就传哪种就行了
LokiSharp
2019-08-29 13:11:37 +08:00
get 也可以带 body 的啊
whitev2
2019-08-29 13:34:16 +08:00
@Vegetable #14 A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.没有说不行,只是服务端可能不拿来用而已

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/596134

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX