后端通过HttpServletRequest.getInputStream获取消息体时,发现读取不出,代码如下:
@PostMapping("/test2")
public String test2(HttpServletRequest request) throws IOException {
BufferedReader reader=new BufferedReader(new InputStreamReader(request.getInputStream(),"utf-8"));
String str=null;
while((str=reader.readLine())!=null){
System.out.println(str);
}
return "ok";
}
然后使用curl命令发起请求:
$ curl -v --data "name=tom&password=123456" http://localhost:8080/test2
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /test2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 24
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 24 out of 24 bytes
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 2
< Date: Wed, 05 Jun 2019 08:28:51 GMT
<
* Connection #0 to host localhost left intact
ok
然而后端无输出,这是因为Spring MVC检测到Content-Type: application/x-www-form-urlencoded,已经先一步读取并解析了。因此后端可用下列方法读取:
@PostMapping("/test")
public String test(String name,String password) throws IOException {
System.out.println(name);
System.out.println(password);
return "ok";
}
如果非要使用HttpServletRequest.getInputStream读取请求消息体呢?那就防止Spring MVC预先读取就行了,比如设置Content-Type: text/*,代码如下所示:
$ curl -v --data "bbbbb" -H "Content-Type: text/*" http://localhost:8080/test2
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /test2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: text/*
> Content-Length: 5
>
* upload completely sent off: 5 out of 5 bytes
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 2
< Date: Wed, 05 Jun 2019 08:31:28 GMT
<
* Connection #0 to host localhost left intact
ok
此时后端能够正确打印bbbb了。
本文详细介绍了在SpringMVC框架下,如何正确处理GET与POST请求的消息体读取。针对POST请求,当Content-Type为application/x-www-form-urlencoded时,SpringMVC会预先读取并解析消息体,导致后端无法通过HttpServletRequest.getInputStream()读取。文章提供了两种解决方案:一是直接使用SpringMVC提供的参数注入方式读取;二是改变Content-Type为text/*,避免SpringMVC的预先读取。
1327

被折叠的 条评论
为什么被折叠?



