关于 GET 请求中的数组格式 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DreamSpace
V2EX    Java

关于 GET 请求中的数组格式

  •  
  •   DreamSpace 2019-08-29 11:13:15 +08:00 14976 次点击
    这是一个创建于 2315 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    接口:

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

    参数:

     /geList?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 请求传输数组参数的方式百花齐放,各种格式都有,归纳了一下,大概以下三种格式:

    • 格式 1:?groupIdList=2&groupIdList=3
    • 格式 2:?groupIdList[]=2&groupIdList[]=3
    • 格式 3:?groupIdList[0]=2&groupIdList[1]=3

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

    39 条回复    2019-08-30 12:54:44 +08:00
    mikoshu
        1
    mikoshu  
       2019-08-29 11:19:19 +08:00
    get 请求传啥数组 让他直接把字符串用逗号隔开给你呗
    chendy
        2
    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
        3
    chendy  
       2019-08-29 11:20:55 +08:00
    忘了说 n=1,2,3,4 或者 n=1&n=2&n=3&n=4 至少 SpringMVC 可以直接用数组和集合接
    baronOvO
        4
    baronOvO  
       2019-08-29 11:20:58 +08:00
    我觉得 1 楼说的对
    rzti483NAJ66l669
        5
    rzti483NAJ66l669  
       2019-08-29 11:21:09 +08:00
    路由都不规范为什么参数格式要规范呢?
    me876
        6
    me876  
       2019-08-29 11:29:26 +08:00   5
    让前端用 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
        7
    index90  
       2019-08-29 11:31:14 +08:00
    记得是推荐格式 1
    whitev2
        8
    whitev2  
       2019-08-29 11:31:20 +08:00
    get 请求也是可以有请求体的,放请求体里

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

    @ipwx 因为是查询数据的接口,具有幂等性的,所以使用的是 GET
    ipwx
        11
    ipwx  
       2019-08-29 11:50:52 +08:00 via Android
    @DreamSpace 我个人觉得幂等性这种概念在这个例子上不重要。首先,批量接口组合数太多,基本没有 http 层缓存的价值。其次,get 参数无法应对大量 ID 的请求,还是得上 post。那些说 get 加上 body 的做法,我觉得那比违反所谓的幂等性更糟糕。综上,我觉得该用 post
    wysnylc
        12
    wysnylc  
       2019-08-29 11:57:59 +08:00
    1 是正确的 2,3 是什么鬼
    现在一般都转成 json &n=[1,2,3]这种形式传输
    PerpetualHeng
        13
    PerpetualHeng  
       2019-08-29 12:11:51 +08:00
    我先说第一点,从来没有 url 传参上会带上"[]"这种符号,即使是数据也是第一种方式。
    第二传数组一般都是搞成 json 传,后端转一下。
    涉及到这种传数组的请求,数据大小可以无限制,还是用 post 吧。
    Vegetable
        14
    Vegetable  
       2019-08-29 12:15:39 +08:00
    DavidNineRoc
        15
    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
        16
    DavidNineRoc  
       2019-08-29 12:29:34 +08:00
    之所以不行的原因,多半是因为你前端对象没有 urlencode 吧
    TabGre
        17
    TabGre  
       2019-08-29 12:34:09 +08:00 via iPhone
    6 楼说的有道理,前端可以自己拼接成你可以解析的形式,手动或者 qs 库
    Sparetire
        18
    Sparetire  
       2019-08-29 12:41:00 +08:00 via Android
    都可以,事实上就 HTTP 而言并没有限制你用哪种,甚至也不需要是 key=value 这样的格式,也都是合法的,这些格式都是框架的约定而已
    所以后端能处理哪种就传哪种就行了
    LokiSharp
        19
    LokiSharp  
       2019-08-29 13:11:37 +08:00
    get 也可以带 body 的啊
    whitev2
        20
    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.没有说不行,只是服务端可能不拿来用而已
    Vegetable
        21
    Vegetable  
       2019-08-29 14:53:41 +08:00   1
    @DavidNineRoc 1 是可以的,不会覆盖,世界上不是只有你一个明白人。
    MonoLogueChi
        22
    MonoLogueChi  
       2019-08-29 15:05:57 +08:00 via Android
    我以前也写过数组,感觉 1 用的比较多,在网上也看过别人用 2 和 3 这种,我自己也用过 1 这种格式。另外路由写好了怎么搞都可以,比如 a.com/api/query/300,301,302,303,使用后面这种格式的时候,fetch 请求特别的方便。

    springboot 没用过,我也不知道怎么搞才能支持后面的,感觉这种东西应该尽量让前端去修改请求,而不是后端修改接口
    sujin190
        23
    sujin190  
       2019-08-29 15:36:11 +08:00
    @whitev2 #20 但是浏览器包括大部分的库实现都会忽略 GET 请求中发送的 body,所以,协议说可以并没有什么用,还是得看现实啊
    azh7138m
        24
    azh7138m  
       2019-08-29 15:46:35 +08:00   2
    @DavidNineRoc
    1 必然受到支持
    https://tools.ietf.org/html/rfc6570#section-3.2.8

    我推荐 2,解析不了就是后端太蔡了(
    willxiang
        25
    willxiang  
       2019-08-29 16:20:24 +08:00
    直接 24L 连接里选“?list=red,green,blue ”这种不是一目了然了吗,后端拿到直接逗号分割
    SoloCompany
        26
    SoloCompany  
       2019-08-29 16:29:42 +08:00
    以 jquery 为例子

    假设请求为: {a:{one:1, two:2, three:3}, b:[1,2,3]}
    需要 uri encode

    那么
    传统风格编码为: a=[object+Object]&b=1&b=2&b=3
    即 格式 1
    因为传统风格并不支持 object 嵌套, a 会被 to string 然后丢失信息

    后来改进的风格编码为
    a[one]=1&a[two]=2&a[three]=3&b[]=1&b[]=2&b[]=3
    即 格式 2

    格式 3 我暂时没见过哪个框架会使用
    momocraft
        27
    momocraft  
       2019-08-29 16:37:07 +08:00
    复杂参数没有规范
    我记得 rfc 连 uri query 的严格定义都无
    x66
        28
    x66  
       2019-08-29 17:09:21 +08:00
    URL 都不标准,为何这么在意参数,用 POST 大法好
    xiangyuecn
        29
    xiangyuecn  
       2019-08-29 17:26:33 +08:00
    各位大佬,请教一下,Map<String,String> 接口有没有实现了多值的字典类呀? C# 有 NameValueCollection,java 不知道是哪个类,注意:是<String,String> 不是<String, List<String>>哦


    因为至今没有学会如何生成一个正常的 Android WebView 响应 WebResourceResponse,因为它的一个参数 Map<String, String> responseHeaders 我不知道用什么类的实例去填

    典型的根请求参数一样,这是一个多值的问题,比如 Set-Cookie 响应头就见得多的是很多个

    https://developer.android.google.cn/reference/android/webkit/WebResourceResponse.html#WebResourceResponse(java.lang.String,%20java.lang.String,%20int,%20java.lang.String,%20java.util.Map%3Cjava.lang.String,%20java.lang.String%3E,%20java.io.InputStream)
    chocotan
        30
    chocotan  
       2019-08-29 17:35:47 +08:00
    错误提示里规范都出来了,很显然是没有 urlencode
    quericy
        31
    quericy  
       2019-08-29 18:09:48 +08:00   3
    不建议用格式 1,不同语言和容器对同名参数的默认处理方式可能会不一样。
    如果无法确保服务端配置合理的话,可能会有 HTTP 参数污染(HPP)攻击的风险
    Alexhohom
        32
    Alexhohom  
       2019-08-29 18:43:16 +08:00 via Android
    @Vegetable 不会覆盖,那用什么方法取值呢?需要自写解析函数吗?
    w516322644
        33
    w516322644  
       2019-08-29 18:45:04 +08:00
    我记得 1 被覆盖过啊。
    后来就是 2 那种
    w516322644
        34
    w516322644  
       2019-08-29 18:47:58 +08:00
    @willxiang 这种唯一问题,就是怕字符串有,
    dany813
        35
    dany813  
       2019-08-29 19:56:49 +08:00
    用 qs 库吧
    lululau
        36
    lululau  
       2019-08-29 20:00:35 +08:00 via iPhone
    第一种是 servlet 支持的,springmvc 三种都可以
    no1xsyzy
        37
    no1xsyzy  
       2019-08-30 10:06:35 +08:00
    这么烦直接 jsonrpc 好不好啊
    zjyl1994
        38
    zjyl1994  
       2019-08-30 11:33:12 +08:00
    我们一般用的都是逗号分隔的字符串
    luozic
        39
    luozic  
       2019-08-30 12:54:44 +08:00
    为啥不 urlencode,服务端获取的请求到底长啥样?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1077 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 23:11 PVG 07:11 LAX 15:11 JFK 18:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86