1

我正在尝试在我们的基于 Struts 的应用程序中记录 HTTP POST 请求的原始正文,该应用程序在 Tomcat 6 上运行。我发现之前关于 SO 的一篇文章有​​些帮助,但接受的解决方案在我的应用程序中无法正常工作案子。问题是,我只想在某些情况下记录 POST 正文,在记录后让 Struts 从正文中解析参数。目前,在我编写的过滤器中,我可以从 HttpServletRequestWrapper 对象读取和记录正文,但之后 Struts 找不到任何要解析的参数,因此 DispatchAction 调用(取决于请求中的参数之一)失败。

我对 Struts 和 Tomcat 源代码进行了一些挖掘,发现将 POST 主体存储到字节数组中并基于该数组公开 Stream 和 Reader 并不重要;当需要解析参数时,Tomcat 的 Request 对象会访问其内部的 InputStream,此时该 InputStream 已经被读取。

有谁知道如何正确实现这种日志记录?

4

3 回答 3

2

事实上,Struts 并不解析参数,它依赖于 Servlet 容器来完成。并且一旦容器读取了 inputStream 以创建参数 Map,当然就没有什么可读取的了。在 Tomcat 实现中,如果您首先读取 inputStream,那么 getParameter* 系列方法就没有什么可做的了,因为正如您正确指出的那样,它不使用 getInputStream 或 getReader,而是在内部访问其优化的读取器。因此,您在 ServletRequestWrapper 中的唯一解决方案是覆盖 getInputStream、getReader 和 Struts 读取参数所依赖的 getParameter* 系列。也许您可以查看 org.apache.catalina.util.RequestUtil 以不重复 POST 正文解析部分。

于 2010-03-21T14:48:33.217 回答
0

问题中的链接过滤器示例看起来不错,应该可以工作。也许您在Struts 调度程序过滤器web.xml 之后定义它。那么解析和记录请求正文并使其仍可用于 Struts 确实为时已晚。您需要在 Struts 调度程序过滤器之前声明此过滤器。过滤器排序很重要,它们按照定义的顺序被调用web.xml

于 2010-03-15T18:10:52.973 回答
0

您在过滤器中要做的就是完整阅读帖子内容,然后将请求传递给链;用你自己的返回输入流。例如,您将帖子读取到磁盘上的文件,然后当您调用时:

chain.doFilter(new ServletRequest() {}, response);

您可以将类的大多数方法调用委托给原始请求,但是当需要打开输入流时,您需要从磁盘上的文件中读取。

您需要确保不会泄漏资源,因为这将被频繁调用,并且如果操作不正确可能会造成伤害。

于 2010-03-15T17:37:19.117 回答