我的情况是我的应用程序需要检查POST请求的内容/数据/正文/有效负载而不更改后续getParameter调用的结果。
从inputStream中读取正文:
可以使用request.getInputStream
中的InputStream或request.getReader
中的BufferedReader来读取正文。
阅读POST参数:
POST请求通常包括请求正文中的请求参数。可以使用getParameter
检索这些内容。
问题:
第一个getParameter
调用在内部解析inputStream并将所有参数插入到参数HashMap中。它要求inputStream仍然包含用于解析的内容。因此,人们无法检查内容,仍然有一个有效的getParameter调用。
建议(但不充分)解决方案
创建一个请求包装器,用于缓存输入流并返回getInputStream的缓存。
我已经看到该解决方案在整个网络上都有建议,但它不起作用,因为getParameter
实际上并没有调用getInputStream
,而是指向隐藏在请求对象中的原始inputBuffer 。我已经尝试过,无论是在Servlet中还是使用过滤器
我能想到的唯一解决方案是重写getParameter以手动解析缓存的输入流。但这感觉不错。
有没有人有其他选择? (这是Tomcat 5.5)这感觉它应该是一个常见的用例;我简直不敢相信它有多难。
答案 0 :(得分:1)
(这是一个相当古老的tomcat,我假设升级到更现代的tomcat不是一种选择。)
您想要做的是要求拦截包装底层InputStream的具体HttpServletResponse对象的构造。将InputStream包装在推回输入流(或等效的)中是必要的。
Tomcat 5.5太老了我甚至无法想象如何“正常”完成它,但也许你可以编写一个过滤器,它使用反射来到达并在具体的请求对象中交换InputStream对象。
答案 1 :(得分:1)
正如@caskey所建议的,一种可能的解决方案是使用反射来将inputBuffer替换为可重放的inputbuffer。但我没有使用那种方法,因为它感觉很顽皮。
相反,我在一个过滤器中创建了一个请求包装器,它将输入流读入一个字节数组,并返回一个新的InputStream
,在该数组周围内部使用ByteArrayInputStream
进行所有getInputStream
调用。
在读取字节数组的输入流后,我通过解析有效负载来创建参数映射。我合并了超类'参数映射以支持带有查询参数的GET案例。我已覆盖所有getParameter *()方法以使用此参数映射。
我使用apache.axis.utils.IOUtils.readFully
轻松读取字节数组中的流。我目前正在使用javax.servlet.http.HttpUtils.parsePostData
将数据解析为参数映射。 HttpUtils.parsePostData
实际上已被弃用,因此当我找到它时,我可能会用更好的版本替换它。
但这很有效,耶!