我最近发现了在日志记录时使用MDCs的魔力。它工作得很完美。
我有以下方法:
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。如果它没有--或者我被托管在另一个不是的地方--我实际上是在永远地扩展地图--或者至少在主机重新启动之前。
我认为我的问题的本质是-是否有一个事件我可以检测到,表明一个特定的会话或线程已经完成,并即将被释放。
发布于 2014-01-15 12:43:05
与其将调用放入每个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中注册相关的类,容器就应该处理其余的类。
https://stackoverflow.com/questions/21137307
复制相似问题