我正在尝试在我们的基于Struts的应用程序中记录HTTP POST请求的原始体,在Tomcat 6上运行。我在SO上发现了一个previous post,这有点帮助,但是接受的解决方案没有在我的情况下工作正常。问题是,我只想在某些情况下记录POST主体,和让Struts在记录后解析主体中的参数。目前,在我编写的Filter中,我可以从HttpServletRequestWrapper对象中读取和记录正文,但是之后Struts找不到任何要解析的参数,因此DispatchAction调用(取决于请求中的一个参数)失败。
我通过Struts和Tomcat源代码进行了一些挖掘,发现将POST主体存储到字节数组中并基于该数组公开Stream和Reader并不重要;当需要解析参数时,Tomcat的Request对象访问其内部InputStream,该时间已经被读取。
有没有人知道如何正确实现这种日志记录?
答案 0 :(得分:2)
实际上,Struts不解析参数,它依赖于Servlet容器来做到这一点。一旦容器读取了inputStream来创建参数Map,当然没有什么可读的。在Tomcat实现中,如果您首先读取inputStream,那么getParameter *系列方法就没有任何工作可做了,因为正如您正确指出的那样,它不使用getInputStream或getReader,而是在内部访问其优化的读取器。 因此,ServletRequestWrapper中唯一的解决方案是覆盖getInputStream,getReader和Struts依赖的getParameter *系列来读取参数。也许您可以查看org.apache.catalina.util.RequestUtil以不复制POST正文解析部分。
答案 1 :(得分:0)
您在过滤器中需要做的就是完整阅读帖子内容,然后再将请求传递给链接;用你自己的回输输入流。例如,您在磁盘上读取要发送的文件,然后在您致电时阅读:
chain.doFilter(new ServletRequest() {}, response);
您可以将类的大多数方法调用委托给原始请求,但是当打开输入流时,您需要从磁盘上的文件中读取。
您需要确保不会泄漏资源,因为这会频繁调用,如果操作不正确会造成伤害。
答案 2 :(得分:0)
问题链接过滤器示例看起来很好,应该可行。也许你是在Struts调度程序过滤器之后的web.xml
中定义它。那么解析和记录请求主体确实为时已晚,但仍然可以将它用于Struts。您需要在Struts调度程序过滤器之前声明此过滤器。过滤器排序很重要,它们在web.xml
中定义时按顺序调用。