10

我有一个 spring-boot Web 应用程序,它利用 logback 的 MDC 上下文来用自定义数据丰富日志。我有以下实现,它使一些与“customKey”关联的自定义数据可用,并且在将 %X{customKey} 添加到 logback 配置中的日志记录模式后,它会正确记录:

public class MDCFilter extends OncePerRequestFilter implements Ordered {

@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
        HttpServletResponse httpServletResponse,
        FilterChain filterChain) throws ServletException, IOException {
        try {

            MDC.put("customKey", "someValue");          

            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } catch(Throwable t) {
            LOG.error("Uncaught exception occurred", t);
            throw t;
        } finally {
            MDC.remove("customKey");
        }
    }

    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE - 4;
    }
}

只要没有抛出未捕获的异常,这就可以正常工作。为了处理这些,我有一个控制器建议。遗憾的是,在登录控制器建议期间,MDC 不再可用,因为它已经被清理过了。如果我理解正确,spring 通过使用 HandlerExceptionResolverComposite 确定负责的 ExceptionHandler - 实现以最低优先级注册自身 - 因此它在 MDC 已被清理后排在最后。

我现在的问题是:我应该如何注册我的过滤器,以便在登录控制器建议期间 MDC 仍然可用?

我认为一种选择是从过滤器的 finally 块中删除 MDC.remove(...) 调用,而是实现一个 ServletRequestListener ,它在 requestDestroyed - 方法中清理 MDC。但是由于过滤器在多个 Web 模块中使用,我需要确保 ServletRequestListener 也在每个现有的和预期的模块中与 MDCFilter 一起声明,这对我来说似乎很容易出错。此外,如果负责将数据添加到 MDC 的过滤器也负责将其删除,我会更喜欢它。

4

0 回答 0