2010-01-28 7 views
26

Ich versuche zu protokollieren (nur um Konsole schreiben jetzt der Einfachheit halber) die endgültige gerenderten HTML, die von der HttpServletResponse zurückgegeben wird. (Das heißt den Körper) Zu diesem Zweck Ich bin mit dem HandlerInterceptorAdapter von Spring MVC wie so:Logging Response Body (HTML) von HttpServletResponse mit 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()); 
    } 
} 

Dies funktioniert wie erwartet und ich sehe die HTTP-Response-Header in der Konsole. Meine Frage ist, ob es eine relativ einfache Möglichkeit gibt, den gesamten Antworttext (d. H. Endgültig gerenderten HTML-Code) auf der Konsole zu protokollieren, ohne mit PrintWriter, OutputStream und ähnlichem auf Huckepacks zurückgreifen zu müssen.

Vielen Dank im Voraus.

+0

Diese in der Regel mit Hilfe von getan der Container .... was machst du das hier? – skaffman

+0

Ich führe es innerhalb von Jetty 7 über das Jetty-Maven-Plugin, aber ich sehe nicht, warum das wichtig sein sollte. Ich möchte die HTML-Antwort sehen, die der Browser erhalten wird. – csamuel

Antwort

21

Dies wäre besser, ein Servlet mit Filter anstatt einer Feder HandlerInterceptor, aus dem Grunde, dass ein Filter dürfen die Anfrage und/oder Antwortobjekte ersetzen, und man diesen Mechanismus verwenden, könnte die Antwort mit einem Wrapper zu ersetzen welche die Antwortausgabe protokolliert.

Dies würde erfordern Schreiben einer Unterklasse von HttpServletResponseWrapper, überschreiben getOutputStream (und möglicherweise auch getWriter()). Diese Methoden würden OutputStream/PrintWriter Implementierungen zurückgeben, die zusätzlich zum Senden an ihr ursprüngliches Ziel den Antwortstrom in ein Protokoll abzapfen. Ein einfacher Weg, dies zu tun ist TeeOutputStream von Apache Commons IO, aber es ist nicht schwer, sich selbst zu implementieren.

Hier ist ein Beispiel für die Art von Sache, die Sie tun können, die Verwendung von Spring machen GenericFilterBean und DelegatingServletResponseStream sowie TeeOutputStream, die Dinge einfacher zu machen:

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

Dies alles STDOUT protokolliert. Wenn Sie sich in eine Datei einloggen wollen, wird es sehr viel komplexer, indem Sie sicherstellen, dass die Streams geschlossen werden und so weiter, aber das Prinzip bleibt gleich.

+0

Tatsächlich wird es komplizierter, da close nicht auf dem DelegatingServletOutputStream aufgerufen wird, da der Wrapper zu dem Zeitpunkt, zu dem der Container den Stream schließt, nicht mehr im Bereich ist. Irgendwelche Ideen, wie Sie das machen könnten? – Ellis

9

Wenn Sie (logback) als Protokollierungsumgebung verwenden (oder in Betracht ziehen), gibt es einen netten Servlet-Filter, der genau das tut. Überprüfen Sie das Kapitel TeeFilter in der documentation.

6

Ich habe nach einer Möglichkeit gesucht, vollständige HTTP Request/Response für eine Weile zu protokollieren und entdeckte, dass es für mich in der Tomcat 7 RequestDumperFilter gelöst wurde. Es funktioniert wie von einem Tomcat 7-Container beworben. Wenn Sie es in Jetty verwenden möchten, funktioniert die Klasse gut eigenständig oder, wie ich es getan habe, kopiert und an die spezifischen Bedürfnisse meiner Umgebung angepasst.

+0

Sieht aus wie dieser Filter in dieser Antwort auch behandelt wird: http://stackoverflow.com/questions/5672904/replacement-for-requestdumpervalve-in-tomcat-7. –

+1

an Mr. Twiggs, Tomcat 7 RequestDumperFilter kann nur Header ablegen, was sehr einfach ist. – Justin

1

Ich habe eine kleine Bibliothek spring-mvc-logger über Maven Central zur Verfügung gestellt.

In pom.xml:

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

zu web.xml hinzufügen:

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

log4j.xml hinzufügen:

ist
<logger name="com.github.isrsal.logging.LoggingFilter"> 
    <level value="DEBUG"/> 
</logger> 
Verwandte Themen