5

私は最近、ロギング時にMDCを使用する魔法を発見しました。それは完全に機能します。

私は次の方法を持っています:

public static final String MDC_CLIENT="client";
public static final String MDC_SESSION="session";
public static final String MDC_DEVICE="device";

// Called for every request.
public static void request(final HttpServletRequest request) {
  // The MDC is a thread-local storage accessable from the log formatter.
  MDC.put(MDC_CLIENT, String.format("%s:%s", request.getRemoteHost(), request.getRemotePort()));
  HttpSession session = request.getSession();
  MDC.put(MDC_SESSION, session.getId());
  MDC.put(MDC_DEVICE, (String)session.getAttribute("device"));
  // Also record the context.
  setContext(session.getServletContext());
}

これは、すべての jsp の最初のアクションとして呼び出されます。これにより、セッションの詳細をログでうまく追跡できます。

removeただし、これらのマップ エントリのタイミングをどのように知ることができますか? マップを整理するには、どのイベントを監視する必要がありますか?

Tomcat でホストしています。スレッドを再利用する場合、これらは本質的にスレッドローカルであるため、メモリリークは発生しません。そのため、スレッドが最後に使用されたときからそれぞれputが古いものを上書きします。putそうでない場合、またはホストされていないものでホストされている場合、基本的にマップを永遠に成長させるか、少なくともホストを再起動するまで成長させます。

私の質問の本質は、特定のセッションまたはスレッドが終了し、解放されようとしていることを示すイベントが検出できるかどうかです。

4

1 に答える 1

8

すべての JSP に呼び出しを入れるのではなく、リクエストの開始時と終了時の両方で通知を受けるServletRequestListenerを登録します。

public class MDCListener implements ServletRequestListener {
  public void requestInitialized(ServletRequestEvent e) {
    YourUtilityClass.request((HttpServletRequest)e.getServletRequest());
  }

  public void requestDestroyed(ServletRequestEvent e) {
    YourUtilityClass.tearDown((HttpServletRequest)e.getServletRequest());
  }
}

または、通常のリクエスト処理フローをラップできるフィルターを使用することもできます。

void doFilter(ServletRequest request, ServletResponse response,
              FilterChain chain) throws IOException, ServletException {
  setupMDC();
  chain.doFilter(request, response);
  tearDownMDC();
}

どちらの方法でも、関連するクラスを登録するだけweb.xmlで、コンテナーが残りを処理する必要があります。

于 2014-01-15T12:43:05.427 に答える