读取HTTPServletRequest的POST主体然后在Tomcat中调用getParameter

时间:2013-08-28 13:31:29

标签: java tomcat servlets post tomcat5.5

我的情况是我的应用程序需要检查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)这感觉它应该是一个常见的用例;我简直不敢相信它有多难。

2 个答案:

答案 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实际上已被弃用,因此当我找到它时,我可能会用更好的版本替换它。

但这很有效,耶!