POST 请求体无法重复读取的原因与解决方案
在 Java Web 开发中,经常会遇到 “POST 请求体只能读取一次” 的问题:当过滤器(Filter)读取请求体后,Servlet 中再次读取时会返回空数据。这一现象与请求流的底层实现密切相关,本文将解析其原因,并提供基于请求包装类的解决方案。
为什么 POST 请求体无法重复读取?
POST 请求体的内容通过输入流(ServletInputStream)读取,而输入流具有一次性读取的特性,核心原因如下:
1. 输入流的 “消费性”
输入流(如 CoyoteInputStream,Tomcat 的实现)本质上是对底层字节流的封装,其读取过程是 “消费性” 的:
- 读取数据时,流的指针会向后移动;
- 当流读取完毕(指针到达末尾),再次读取会返回
-1(表示已读完); - 流关闭后(如
close()被调用),无法再次打开或重置。
2. Tomcat 中的具体实现
以 Tomcat 为例,getInputStream() 返回的 CoyoteInputStream 内部依赖 InputBuffer 存储请求体数据。当数据被读取后,InputBuffer 中的缓存会被清空,且流的 closed 状态会被标记为 true:
1 | // Tomcat 的 CoyoteInputStream 部分源码 |