捕获并logging响应主体
我有一个处理某些HTTP请求和响应的servlet。 我想在发送回客户端之前logging响应主体。 有没有什么方法可以捕获响应主体,然后将其作为Servlet中的HttpServletResponse
对象发送?
如果我正确理解你,你想logging响应正文 ? 这是一个相当昂贵的任务,但如果这是业务需求…
正如@duffymo指出的,一个Filter
是一个合适的地方。 您可以通过用一个HttpServletResponseWrapper
实现replace传入的ServletResponse
来捕获响应主体,该实现用自己的实现replaceHttpServletResponse#getWriter()
,该实现将响应主体复制到某个缓冲区中。 继续更换响应的filter链后,只需logging副本。
以下是doFilter()
方法的doFilter()
示例:
public void doFilter(ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException { final CopyPrintWriter writer = new CopyPrintWriter(response.getWriter()); chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) { @Override public PrintWriter getWriter() { return writer; } }); logger.log(writer.getCopy()); }
以下是CopyPrintWriter
外观:
public class CopyPrintWriter extends PrintWriter { private StringBuilder copy = new StringBuilder(); public CopyPrintWriter(Writer writer) { super(writer); } @Override public void write(int c) { copy.append((char) c); // It is actually a char, not an int. super.write(c); } @Override public void write(char[] chars, int offset, int length) { copy.append(chars, offset, length); super.write(chars, offset, length); } @Override public void write(String string, int offset, int length) { copy.append(string, offset, length); super.write(string, offset, length); } public String getCopy() { return copy.toString(); } }
将此filter映射到您想为其logging响应的url-pattern
。 请记住,图像,CSS,JS文件等二进制/静态内容将不会以这种方式logging。 您希望通过使用足够特定的url-pattern
(例如*.jsp
或仅在所讨论的servlet-name
中排除它们。 如果你想logging二进制/静态内容(我没有看到任何好处),那么你需要以同样的方式replaceHttpServletResponse#getOutputStream()
。
也许一个servletfilter可以帮助你。 把它看作是面向方面的HTTP编程。
BalusC答案的替代方法使用TeeOutputStream在时间写入两个输出stream。
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); final PrintStream ps = new PrintStream(baos); chain.doFilter(req,new HttpServletResponseWrapper(res) { @Override public ServletOutputStream getOutputStream() throws IOException { return new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps) ); } @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(new DelegatingServletOutputStream (new TeeOutputStream(super.getOutputStream(), ps)) ); } }); //Get Response body calling baos.toString(); }
我做了一个没有第三方依赖的OutputStream版本,类似于@pdorgambide。 你可以在这个链接find。