【问题标题】:Struts and logging HTTP POST request bodyStruts 和记录 HTTP POST 请求正文
【发布时间】:2011-01-27 18:29:27
【问题描述】:

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

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

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

【问题讨论】:

    标签: java tomcat logging servlets http-post


    【解决方案1】:

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

    【讨论】:

    • 我希望我不必这样做,但看起来这是唯一的选择。
    【解决方案2】:

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

    【讨论】:

    • 过滤器被定义为链中的第一个过滤器。一旦过滤器运行,流就会被清空,甚至请求的 servlet 也无法使用参数,更不用说 Struts。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 正如 BalusC 所说,代码已经做到了。问题出在被覆盖的方法中。 Tomcat 的 RequestFacade 允许我覆盖 getInputStream() 方法,但这还不够好,因为 Request(在其 parseParameters() 方法中)使用受保护的 getStream() 方法。
    猜你喜欢
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    相关资源
    最近更新 更多