场景说明

如下代码:
原以为 param 和 body 都可以得到 JSON 字符串,但是实际上只有 body 有数据,即通过注解获得的数据;

  1. @PostMapping("/body2")
  2. public ResponseEntity<String> test2(@RequestBody String body, HttpServletRequest request) {
  3. String param = getBody(request);
  4. log.info("param : {} ", param);
  5. log.info("body : {} ", body);
  6. return ResponseEntity.ok("Good");
  7. }
  8. /**
  9. * 获取POST请求中Body参数
  10. *
  11. * @param request request
  12. * @return 字符串
  13. */
  14. public String getBody(HttpServletRequest request)

具体原因可参考这篇博客:

首先,我们复习一下InputStream read方法的基础知识:

Java InputStream read 方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,InputStream.read方法会返回-1,标志已经读取完了,如果想再次读取,可以调用inputstream.reset方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。

当然,能否reset是有条件的,它取决于 markSupported,markSupported() 方法返回是否可以mark/reset 我们再回头看 request.getInputStream request.getInputStream 返回的值是 ServletInputStream,查看ServletInputStream源码发现,没有重写reset方法,所以查看InputStream源码发现marksupported 返回false,并且reset方法,直接抛出异常。