}
上面的单元测试顺利通过,说明对于 GET 请求我们同样可以使用 Request Body 来发送数据,而且 Spring 的测试框架也支持 GET 发送 body 数据。
再作一个验证,curl 命令, 需要用 -X 指定为 GET 请求,否则 curl 在使用 -d 发送 body 数据时自动切换为 POST 请求
通过 curl -v 可以看到详细的请求响应数据,两个请求的 Content-Length 都是 8, 即 "Get Body" 的长度,它们确实是在 Request Body 中,服务端接送 GET 来的 body 数据也没有半点问题。
下面是通过 Wireshark 捕获到的数据包的样子
如果说通过 Spring 的测试用例以及 curl 命令还有所疑问的话,看上面那张图片就分明的告诉我们是在使用 GET 发送 body 数据的。
但确实有些工具或类库不让我们发送 GET 请求时设置 Body, 例如著名的 Postman, 在选择 GET 时 Body 标签是灰色不可用的。
而且从目前最新的 Apache Http Client 4.5 组件,它的 HttpGet 也不支持设置 Request Body, 因为 HttpGet 没有像 HttpPost 那样的 setEntity(entity) 方法。
另一个 OkHttpClient 库也不支持 GET 发送 Request Body, 当执行下面的代码时
1 new Request.Builder()
2 .url("http://localhost:8080/?id=100")
3 .method("GET", RequestBody.create(MediaType.parse("application/json"), "hello body"))
4 .build();
直接告诉我
1 java.lang.IllegalArgumentException: method GET must not have a request body
最后再试一个 AsyncHttpClient 库
1 Dsl.asyncHttpClient()
2 .prepareGet("http://localhost:8080/?id=100")
3 .setBody("Get Body")
4 .execute()
5 .toCompletableFuture()
6 .thenAccept(System.out::println).join();
输出 "100: Get Body", 证明 AsyncHttpClient 是可以 GET 时发送 Body 数据的。
Apache Http Client 和 OkHttpClient 都不支持 GET 请求发送 Body 数据,而 AsyncHttpClient 是可以的。
那么回过头来想想为什么 HTTP 并未规定不可以 GET 中发送 Body 内容,但却不少知名的工具不能用 GET 发送 Body 数据,所以大致的讲我们仍然不推荐使用 GET 携带 Body 内容,一是因为有可能某些应用服务器也会忽略掉 GET 的 Body 数据。我想更主要是 GET 被设计来用 URI 来识别资源,如果让它的请求体中携带数据,那么通常的缓存服务便失效了,URI 不能作为缓存的 Key;而是http协议是支持GET请求是带请求体的,后端也是可以接受GET请求中的请求体,但是web浏览器会限制GET请求不携带请求体。
但另一方面,如果仅仅是为了读取资源,而需要使用 Body 发送一大批数据时,改用 POST 请求却与 RESTFul 的 POST 语义不相符。这时候或许可以 GET + BODY, 但是不能对该请求以 URI 作为 Key 进行缓存了。
四、参考文章
https://yanbin.blog/why-http-get-cannot-sent-data-with-reuqest-body/#more-8193
https://blog.csdn.net/liushuyul/article/details/113341456?utm_term=gethttp%E6%9C%89%E6%B2%A1%E6%9C%89%E8%AF%B7%E6%B1%82%E4%BD%93&utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~sobaiduweb~default-0-113341456&spm=3001.4430
本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/15133243.html