2010-01-28 14 views
26

Sto tentando di registrare (solo per console scrivere ora per semplicità) l'HTML reso finale che verrà restituito da HttpServletResponse. (Vale a dire il corpo) A tal fine, sto usando la HandlerInterceptorAdapter da Spring MVC in questo modo:Logging response body (HTML) da HttpServletResponse utilizzando 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()); 
    } 
} 

Questo funziona come previsto e vedo le intestazioni di risposta HTTP nella console. La mia domanda è se c'è un modo relativamente semplice per registrare l'intero corpo della risposta (cioè HTML reso finale) alla console senza dover ricorrere a jump jump con PrintWriters, OutputStream e simili.

Grazie in anticipo.

+0

Questo è solitamente fatto con l'aiuto di il contenitore ... a cosa stai lavorando? – skaffman

+0

Lo sto eseguendo all'interno del Jetty 7 tramite il jetty-maven-plugin, ma non vedo perché questo dovrebbe avere importanza. Voglio vedere la risposta html che il browser sta per ricevere. – csamuel

risposta

21

questo sarebbe meglio fatto utilizzando una Servlet Filter piuttosto che una molla HandlerInterceptor, per la ragione che un Filter è consentito di sostituire la richiesta e/o di risposta degli oggetti, e si potrebbe utilizzare questo meccanismo per sostituire la risposta con un involucro che registra l'output della risposta.

Ciò comporterebbe la scrittura di una sottoclasse di HttpServletResponseWrapper, che sostituisce getOutputStream (ed eventualmente anche getWriter()). Questi metodi restituiscono le implementazioni OutputStream/PrintWriter che prelevano il flusso di risposta in un registro, oltre a inviare alla destinazione originale. Un modo semplice per farlo è utilizzare TeeOutputStream da Apache Commons IO, ma non è difficile da implementare.

Ecco un esempio del tipo di cosa che si potrebbe fare, facendo uso di Primavera di GenericFilterBean e DelegatingServletResponseStream, così come TeeOutputStream, per rendere le cose più facili:

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

Questo registra tutto ciò che a STDOUT. Se si desidera accedere a un file, questo diventerà molto più complesso, con ciò assicurandosi che gli stream vengano chiusi e così via, ma il principio rimane lo stesso.

+0

In effetti diventa più complicato in quanto non viene richiamato su DelegatingServletOutputStream poiché il wrapper è fuori ambito nel punto in cui il contenitore chiude il flusso. Qualche idea su come potresti fare questo? – Ellis

9

Se si utilizza (o si considera) logback come framework di registrazione, è già disponibile un buon filtro servlet che fa esattamente questo. Scopri il capitolo TeeFilter nel documentation.

6

Ho cercato un modo per registrare la richiesta/risposta HTTP completa per un po 'e ho scoperto che è stato risolto per me nello Tomcat 7 RequestDumperFilter. Funziona come pubblicizzato da un contenitore Tomcat 7. Se si desidera utilizzarlo in Jetty, la classe funziona bene stand-alone o, come ho fatto, copiato e adattato alle esigenze specifiche del mio ambiente.

+0

Sembra che questo filtro sia trattato anche in questa risposta: http://stackoverflow.com/questions/5672904/replacement-for-requestdumpervalve-in-tomcat-7. –

+1

a Mr Twiggs, Tomcat 7 RequestDumperFilter può solo scaricare l'intestazione, che è molto semplice. – Justin

1

Ho creato una piccola biblioteca spring-mvc-logger disponibile tramite central central.

Aggiunga al pom.xml:

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

Aggiungi al 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> 

Aggiungi al log4j.xml:

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