Logging response body (HTML) from HttpServletResponse using Spring MVC HandlerInterceptorAdapter

后端 未结 5 2171
夕颜
夕颜 2020-12-03 05:11

I am trying to log (just to console write now for simplicity sake) the final rendered HTML that will be returned by the HttpServletResponse. (i.e. the body) To this end, I a

5条回答
  •  悲&欢浪女
    2020-12-03 05:26

    This would be better done using a Servlet Filter rather than a Spring HandlerInterceptor, for the reason that a Filter is allowed to substitute the request and/or response objects, and you could use this mechanism to substitute the response with a wrapper which logs the response output.

    This would involve writing a subclass of HttpServletResponseWrapper, overriding getOutputStream (and possibly also getWriter()). These methods would return OutputStream/PrintWriter implementations that siphon off the response stream into a log, in addition to sending to its original destination. An easy way to do this is using TeeOutputStream from Apache Commons IO, but it's not hard to implement yourself.

    Here's an example of the sort of thing you could do, making use of Spring's GenericFilterBean and DelegatingServletResponseStream, as well as TeeOutputStream, to make things easier:

    public class ResponseLoggingFilter extends GenericFilterBean {
    
       @Override
       public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
          HttpServletResponse responseWrapper = loggingResponseWrapper((HttpServletResponse) response);     
          filterChain.doFilter(request, responseWrapper);
       }
    
       private HttpServletResponse loggingResponseWrapper(HttpServletResponse response) {
          return new HttpServletResponseWrapper(response) {
             @Override
             public ServletOutputStream getOutputStream() throws IOException {
                return new DelegatingServletOutputStream(
                   new TeeOutputStream(super.getOutputStream(), loggingOutputStream())
                );
             }
          };
       }
    
       private OutputStream loggingOutputStream() {
          return System.out;
       }
    }
    

    This logs everything to STDOUT. If you want to log to a file, it'll get a big more complex, what with making sure the streams get closed and so on, but the principle remains the same.

提交回复
热议问题