如何在Spring boot Tomcat场景中清除线程上下文?
How to clear thread context in Spring boot Tomcat scenario?
我们实现 HandlerInterceptor
以在 preHandle
方法中设置 MDC 线程上下文数据。
然后我们将此数据用于日志记录和指标目的。
但是,如果我们在 afterCompletion
方法中使用 MDC.clear()
清除 MDC 数据,则此后的指标处理程序的宝贵信息将丢失。我说的是 WebMvcTagsProvider
,但我想这适用于所有类型的用例。
既然有线程池,一个线程最终会被重用,并包含一个来自上一个HTTP请求的MDC上下文,这很糟糕!
那么我如何 "wrap" 在设置和完成方法中使用线程?
理想情况下,这将是一个通用的解决方案。我不想更改现有代码。目标是,新的传入请求无法访问以前的 MDC 上下文。
我已经知道如何在 Java EE 世界中解决这个问题,例如:
@Provider
@Priority(Priorities.USER + 1)
public class MdcClearFilter implements ContainerResponseFilter {
@Override
public void filter(
ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
MDC.clear();
}
}
那么我如何在 Spring 引导世界中做同样的事情?
由于 HandlerInterceptor
都在 Servlet 上下文中,因此它们无法跳出。
所以解决方案是使用顺序为 Ordered.HIGHEST_PRECEDENCE
的 servlet Filter
。
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCClearFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
MDC.clear();
}
}
我们实现 HandlerInterceptor
以在 preHandle
方法中设置 MDC 线程上下文数据。
然后我们将此数据用于日志记录和指标目的。
但是,如果我们在 afterCompletion
方法中使用 MDC.clear()
清除 MDC 数据,则此后的指标处理程序的宝贵信息将丢失。我说的是 WebMvcTagsProvider
,但我想这适用于所有类型的用例。
既然有线程池,一个线程最终会被重用,并包含一个来自上一个HTTP请求的MDC上下文,这很糟糕!
那么我如何 "wrap" 在设置和完成方法中使用线程? 理想情况下,这将是一个通用的解决方案。我不想更改现有代码。目标是,新的传入请求无法访问以前的 MDC 上下文。
我已经知道如何在 Java EE 世界中解决这个问题,例如:
@Provider
@Priority(Priorities.USER + 1)
public class MdcClearFilter implements ContainerResponseFilter {
@Override
public void filter(
ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
MDC.clear();
}
}
那么我如何在 Spring 引导世界中做同样的事情?
由于 HandlerInterceptor
都在 Servlet 上下文中,因此它们无法跳出。
所以解决方案是使用顺序为 Ordered.HIGHEST_PRECEDENCE
的 servlet Filter
。
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCClearFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
MDC.clear();
}
}