首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DreamSpace
V2EX  ›  Java

关于 GET 请求中的数组格式

  •  
  •   DreamSpace · 152 天前 · 3352 次点击
    这是一个创建于 152 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    接口:

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

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

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

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

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