Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 何时从MDC中删除_Java_Tomcat_Servlets_Log4j_Mdc - Fatal编程技术网

Java 何时从MDC中删除

Java 何时从MDC中删除,java,tomcat,servlets,log4j,mdc,Java,Tomcat,Servlets,Log4j,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 HttpServle

我最近发现了在登录时使用的魔力。它工作得很好

我有以下方法:

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中的第一个操作。这使我能够在日志中很好地跟踪会话的详细信息

但是-我如何知道何时删除这些映射条目?我应该关注什么样的事件才能让我整理地图

我在Tomcat主持。如果它重新使用线程,那么我不会泄漏内存,因为这些线程本质上是线程本地的,因此每个
put
都将覆盖上次使用线程时的旧
put
。如果它没有-或者我被托管在其他没有的东西下-我实际上是在永久地增长地图-或者至少在主机重新启动之前


我想我的问题的本质是——是否有一个我可以检测到的事件表明某个特定会话或线程已完成并即将释放。

我将注册一个JSP,它在请求启动和完成时都会收到通知,而不是将调用放入每个JSP中:

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
中注册相关类,容器就可以处理其余的类。

工作得非常好!我必须将
com…MDCListener
添加到我的web.xml中。如果MDC值未被删除,会发生什么情况?per@Stefan:回答@prime的问题:如果线程被重新用于另一个请求,并且您没有在请求之间清除MDC,那么您将访问旧请求的值。