Http Servlet 请求在读取一次后会丢失 POST 正文中的参数
在这种情况下,在处理 POST 请求时了解这一点至关重要,参数通常在请求正文中发送。默认情况下,Servlet 容器在第一次访问参数时会消耗输入字符流或二进制流。因此,后续尝试在过滤器链中访问它们会失败。
要解决此问题,需要考虑两种主要方法:
1。拦截器组件:
作为使用过滤器链的替代方案,您可以使用拦截器组件。这些组件可以使用方面来实现,并允许对解析的请求正文进行操作,而无需依赖于所使用的请求输入流。这种方法通常更有效,因为请求 InputStream 仅解析一次以创建您自己的模型对象。
2. HttpServletRequestWrapper:
对于 HTTP 层首选过滤器链的情况,扩展 HttpServletRequestWrapper 是一个有效的方法。此技术涉及消耗请求 InputStream 并缓存字节:
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper { private ByteArrayOutputStream cachedBytes; public MultiReadHttpServletRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { if (cachedBytes == null) cacheInputStream(); return new CachedServletInputStream(cachedBytes.toByteArray()); } @Override public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } private void cacheInputStream() throws IOException { /* Cache the inputstream in order to read it multiple times. For * convenience, I use apache.commons IOUtils */ cachedBytes = new ByteArrayOutputStream(); IOUtils.copy(super.getInputStream(), cachedBytes); } /* An input stream which reads the cached request body */ private static class CachedServletInputStream extends ServletInputStream { private final ByteArrayInputStream buffer; public CachedServletInputStream(byte[] contents) { this.buffer = new ByteArrayInputStream(contents); } @Override public int read() { return buffer.read(); } @Override public boolean isFinished() { return buffer.available() == 0; } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener listener) { throw new RuntimeException("Not implemented"); } } }
通过在将原始请求传递到过滤器链之前使用 MultiReadHttpServletRequest 包装原始请求,可以多次读取请求正文。请注意,此解决方案还有助于通过 getParameterXXX 方法进行多次读取。
编辑:
对于较新版本的 ServletInputStream 接口,需要使用 isReady 和 setReadListener 等其他方法实施的。请参阅此问题以获取更多信息。
以上是为什么我的 Http Servlet 请求在一次读取后会丢失 POST 正文参数?的详细内容。更多信息请关注PHP中文网其他相关文章!