web-dev-qa-db-ja.com

Spring MVC HandlerInterceptorAdapterを使用したHttpServletResponseからの応答本文(HTML)のロギング

HttpServletResponseによって返される最終的にレンダリングされたHTMLをログに記録しようとしています(簡単にするために、今すぐコンソールに書き込みます)。 (つまり、本体)この目的のために、SpringMVCの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());
    }
}

これは期待どおりに機能し、コンソールにHTTP応答ヘッダーが表示されます。私の質問は、PrintWritersやOutputStreamなどでジャンプジャックを行うことなく、応答本文全体(つまり、最終的にレンダリングされたHTML)をコンソールに記録する比較的簡単な方法があるかどうかです。

前もって感謝します。

26
csamuel

これは、Filterという理由で、Spring HandlerInterceptor ではなくサーブレット Filter を使用して行う方が適切です。は、要求オブジェクトや応答オブジェクト、あるいはその両方を置き換えることができます。このメカニズムを使用して、応答を、応答出力をログに記録するラッパーに置き換えることができます。

これには、 HttpServletResponseWrapper のサブクラスを記述し、getOutputStream(および場合によってはgetWriter())をオーバーライドすることが含まれます。これらのメソッドは、元の宛先に送信するだけでなく、応答ストリームをログに吸い上げるOutputStream/PrintWriter実装を返します。これを行う簡単な方法は、 TeeOutputStream from Apache Commons IO を使用することですが、自分で実装するのは難しくありません。

これは、SpringのGenericFilterBeanDelegatingServletResponseStream、およびTeeOutputStreamを使用して、物事を簡単にすることができる種類の例です。

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

これにより、すべてがSTDOUTに記録されます。ファイルにログを記録する場合は、ストリームを確実に閉じるなど、さらに複雑になりますが、原則は同じです。

21
skaffman

ロギングフレームワークとして logback を使用している(または検討している)場合は、まさにそれを実行するニースサーブレットフィルターがすでに利用可能です。 ドキュメント のTeeFilterの章を確認してください。

9
Zoran Regvart

しばらくの間、完全なHTTP要求/応答をログに記録する方法を探していましたが、 Tomcat 7 RequestDumperFilter で解決されていることがわかりました。 Tomcat7コンテナからアドバタイズされたとおりに機能します。 Jettyで使用する場合は、クラスはスタンドアロンで正常に機能するか、私が行ったように、環境の特定のニーズに合わせてコピーおよび適合させます。

6
Mr Twiggs

小さなライブラリを作成しました spring-mvc-logger mavencentralから利用できます。

Pom.xmlに追加します。

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

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>

Log4j.xmlに追加します。

<logger name="com.github.isrsal.logging.LoggingFilter">
    <level value="DEBUG"/>
</logger>
1
Israel Zalmanov