2010-01-28 25 views
26

Estoy intentando iniciar sesión (solo para escribir en consola ahora por simplicidad) el HTML renderizado final que será devuelto por HttpServletResponse. (Es decir, el cuerpo) Con este fin, estoy usando el HandlerInterceptorAdapter de Spring MVC, así:Cuerpo de respuesta de registro (HTML) de HttpServletResponse utilizando Spring MVC HandlerInterceptorAdapter

public class VxmlResponseInterceptor extends HandlerInterceptorAdapter { 
    @Override 
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
     System.out.println(response.toString()); 
    } 
} 

Esto funciona como se espera y veo las cabeceras de respuesta HTTP en la consola. Mi pregunta es si hay una manera relativamente simple de registrar todo el cuerpo de la respuesta (es decir, el HTML renderizado final) en la consola sin tener que recurrir a hacer saltos con PrintWriters, OutputStream y similares.

Gracias de antemano.

+0

Esto se hace generalmente con la ayuda de el contenedor ... ¿en qué estás corriendo esto? – skaffman

+0

Lo estoy ejecutando dentro de Jetty 7 a través de jetty-maven-plugin, pero no veo por qué eso debería importar. Quiero ver la respuesta html que el navegador va a recibir. – csamuel

Respuesta

21

esto sería mejor hacer uso de un servlet Filter en lugar de un resorte HandlerInterceptor, por la razón de que un Filter se le permite sustituir las peticiones y/o de respuesta a los objetos, y se podía utilizar este mecanismo para sustituir la respuesta con una envoltura que registra la salida de respuesta.

Esto implicaría escribir una subclase de HttpServletResponseWrapper, anulando getOutputStream (y posiblemente también getWriter()). Estos métodos devolverían implementaciones OutputStream/PrintWriter que derivan la secuencia de respuesta en un registro, además de enviar a su destino original. Una forma fácil de hacerlo es usar TeeOutputStream desde Apache Commons IO, pero no es difícil implementarlo usted mismo.

He aquí un ejemplo del tipo de cosas que podría hacer, haciendo uso de la primavera de GenericFilterBean y DelegatingServletResponseStream, así como TeeOutputStream, para facilitar las cosas:

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; 
    } 
} 

Este registra todo a la salida estándar. Si desea iniciar sesión en un archivo, se volverá mucho más complejo, con lo que se asegurará de que las transmisiones se cierren, y así sucesivamente, pero el principio sigue siendo el mismo.

+0

De hecho, se vuelve más complicado ya que close no se invoca en DelegatingServletOutputStream ya que el contenedor está fuera del alcance en el momento en que el contenedor cierra la transmisión. ¿Alguna idea sobre cómo puedes hacer esto? – Ellis

9

Si está utilizando (o considerando) logback como su marco de trabajo de registro, hay un buen filtro de servlet ya disponible que hace exactamente eso. Consulte el capítulo de TeeFilter en el documentation.

6

He estado buscando una manera de registrar la solicitud/respuesta HTTP por un tiempo y descubrí que se ha resuelto en el Tomcat 7 RequestDumperFilter. Funciona como se anuncia desde un contenedor Tomcat 7. Si desea usarlo en Jetty, la clase funciona bien de forma independiente o, como lo hice, copiada y adaptada a las necesidades específicas de mi entorno.

+0

Parece que este filtro también se trata en esta respuesta: http://stackoverflow.com/questions/5672904/replacement-for-requestdumpervalve-in-tomcat-7. –

+1

a Mr Twiggs, Tomcat 7 RequestDumperFilter solo puede volcar el encabezado, lo cual es muy simple. – Justin

1

Hice una pequeña biblioteca spring-mvc-logger disponible a través de maven central.

Agregar a pom.xml:

<dependency> 
    <groupId>com.github.isrsal</groupId> 
    <artifactId>spring-mvc-logger</artifactId> 
    <version>0.2</version> 
</dependency> 

Añadir a web.xml:

<filter> 
    <filter-name>loggingFilter</filter-name> 
    <filter-class>com.github.isrsal.logging.LoggingFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>loggingFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

Añadir a log4j.xml:

<logger name="com.github.isrsal.logging.LoggingFilter"> 
    <level value="DEBUG"/> 
</logger> 
Cuestiones relacionadas