Java Logback MDC put()可变对象

Java Logback MDC put()可变对象,java,vaadin,logback,slf4j,mdc,Java,Vaadin,Logback,Slf4j,Mdc,我正在使用Vaadin框架,它对拦截事件的支持很差,我不知道会话或UI何时被激活,所以我无法将它们的ID放入MDC 通常我会: public void onSessionBegin(){ MDC.put("session", VaadinSession.getCurrent().toString()); //<-- String is immutable } public void onSessionEnd(){ MDC.remove("session"); } publ

我正在使用Vaadin框架,它对拦截事件的支持很差,我不知道会话或UI何时被激活,所以我无法将它们的ID放入MDC

通常我会:

public void onSessionBegin(){
    MDC.put("session", VaadinSession.getCurrent().toString()); //<-- String is immutable
}
public void onSessionEnd(){
    MDC.remove("session");
}
public void onSessionBegin(){

MDC.put(“session”,VaadinSession.getCurrent().toString());//您不希望从每个日志记录行的线程局部变量中检索当前会话(这就是
VaadinSession.getCurrent()
所做的)。API使用静态字符串类型,因为这是最快的

Vaadin实际上有
SessionInitListener
SessionDestroyListener
,但这也不是您想要的:MDC是线程本地的,但不是同一会话中的所有请求都在同一线程中处理。因此,在
RequestHandler
的实现中,您必须在每个请求中设置MDC中的值.我认为Vaadin没有用于请求结束的回调接口,因此似乎没有清除值的好地方

更新:在这个答案被接受后,我发现实际上有一种更好的方法来设置和清除该值,这样如果服务器为不同的会话回收线程,它就不会包含错误信息。您应该做的是子类
VaadinServlet
VaadinPortlet
并重写
createServletService()
返回
VaadinServletService
VaadinPortletService
的自定义子类,该子类依次覆盖
requestStart()
requestEnd()
以分别设置和删除MDC中的值

// 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