我正在使用Vaadin框架,它对拦截事件的支持很少,我不知道会话或UI何时被激活,所以我不能将它们的ID放在MDC中。
通常我会:
public void onSessionBegin(){
MDC.put("session", VaadinSession.getCurrent().toString()); //<-- String is immutable
}
public void onSessionEnd(){
MDC.remove("session");
}
但我没有这样的事件,所以我想:
// in the servlet init or wherever
MDC.put("session", new Object(){
public String toString() {
VaadinSession.getCurrent().toString()
};
}); //<-- This is mutable and will be evaluated each time
这样,无论有多少时间会改变会话,在日志中我都会得到当前的会话。
这可能吗?如何使用自定义MDC实现替换logback MDC实现?我应该编辑slf4j和logback的来源吗?
答案 0 :(得分:4)
您不希望从每个日志记录行的线程局部变量中检索当前会话(这是VaadinSession.getCurrent()
所做的)。 API使用静态String类型,因为它是最快的。
Vaadin确实有SessionInitListener
和SessionDestroyListener
,但这也不是你想要的:MDC是线程本地的,但不是同一个会话中的所有请求都在同一个线程内处理。因此,您必须在RequestHandler
的实现中为每个请求设置MDC中的值。我不认为Vaadin在请求结束时有一个回调界面,因此似乎没有理由清除该值。
UPDATE:在这个答案被接受之后,我发现实际上有更好的方法来设置和清除值,这样如果服务器为不同的会话回收线程,它就不会#39 ; t包含虚假信息。您应该做的是子类VaadinServlet
或VaadinPortlet
并覆盖createServletService()
以返回VaadinServletService
或VaadinPortletService
的自定义子类,而后者又会覆盖requestStart()
}和requestEnd()
分别设置和删除MDC中的值。