DreamSpace
V2EX  ›  Java

关于 GET 请求中的数组格式

  •  
  •   DreamSpace · Aug 29, 2019 · 15730 views
    This topic created in 2624 days ago, the information mentioned may be changed or developed.

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

    接口:

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

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

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

    39 replies  •  2019-08-30 12:54:44 +08:00
    mikoshu
    mikoshu
    Aug 29, 2019
    1
    get 请求传啥数组 让他直接把字符串用逗号隔开给你呗
    chendy
    chendy
    Aug 29, 2019
    2
    url 参数本身就是多值的,只不过一般用不到:n=1,2,3,4 或者 n=1&n=2&n=3&n=4
    一旦要用到复杂对象结构和数组,就直接用 POST 吧,省心省事
    chendy
    chendy
    Aug 29, 2019
    3
    忘了说 n=1,2,3,4 或者 n=1&n=2&n=3&n=4 至少 SpringMVC 可以直接用数组和集合接
    baronOvO
    baronOvO
    Aug 29, 2019
    4
    我觉得 1 楼说的对
    rzti483NAJ66l669
    rzti483NAJ66l669
    Aug 29, 2019
    5
    路由都不规范为什么参数格式要规范呢?
    me876
    me876
    Aug 29, 2019❤️5
    6
    让前端用 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
    index90
    Aug 29, 2019
    7
    记得是推荐格式 1
    whitev2
    whitev2
    Aug 29, 2019
    8
    get 请求也是可以有请求体的,放请求体里

    @chendy #2
    ipwx
    ipwx
    Aug 29, 2019 via Android❤️1
    9
    批量的接口为啥不用 post
    DreamSpace
    DreamSpace
    OP
    Aug 29, 2019
    10
    @chendy 感谢,测试了下的以逗号分隔的确可以比较方便的接受

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

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

    我推荐 2,解析不了就是后端太蔡了(
    willxiang
    willxiang
    Aug 29, 2019
    25
    直接 24L 连接里选“?list=red,green,blue ”这种不是一目了然了吗,后端拿到直接逗号分割
    SoloCompany
    SoloCompany
    Aug 29, 2019
    26
    以 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
    momocraft
    Aug 29, 2019
    27
    复杂参数没有规范
    我记得 rfc 连 uri query 的严格定义都无
    x66
    x66
    Aug 29, 2019
    28
    URL 都不标准,为何这么在意参数,用 POST 大法好
    xiangyuecn
    xiangyuecn
    Aug 29, 2019
    29
    各位大佬,请教一下,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
    chocotan
    Aug 29, 2019
    30
    错误提示里规范都出来了,很显然是没有 urlencode
    quericy
    quericy
    Aug 29, 2019❤️3
    31
    不建议用格式 1,不同语言和容器对同名参数的默认处理方式可能会不一样。
    如果无法确保服务端配置合理的话,可能会有 HTTP 参数污染(HPP)攻击的风险
    Alexhohom
    Alexhohom
    Aug 29, 2019 via Android
    32
    @Vegetable 不会覆盖,那用什么方法取值呢?需要自写解析函数吗?
    w516322644
    w516322644
    Aug 29, 2019
    33
    我记得 1 被覆盖过啊。
    后来就是 2 那种
    w516322644
    w516322644
    Aug 29, 2019
    34
    @willxiang 这种唯一问题,就是怕字符串有,
    dany813
    dany813
    Aug 29, 2019
    35
    用 qs 库吧
    lululau
    lululau
    Aug 29, 2019 via iPhone
    36
    第一种是 servlet 支持的,springmvc 三种都可以
    no1xsyzy
    no1xsyzy
    Aug 30, 2019
    37
    这么烦直接 jsonrpc 好不好啊
    zjyl1994
    zjyl1994
    Aug 30, 2019
    38
    我们一般用的都是逗号分隔的字符串
    luozic
    luozic
    Aug 30, 2019
    39
    为啥不 urlencode,服务端获取的请求到底长啥样?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2899 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 76ms · UTC 12:32 · PVG 20:32 · LAX 04:32 · JFK 07:32
    ♥ Do have faith in what you're doing.