【问题标题】:How to determine if the request is NOT the initial request in a Filter?如何确定请求是否不是过滤器中的初始请求?
【发布时间】:2017-11-24 19:14:06
【问题描述】:

我想要做的是以下几点: 修改 logback 以在日志行上写出用户 ID 和请求 ID。 例如

2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA1] message...
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA2] message...
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassB:MethodB1] message...

请注意,requestId 保持不变,因为它是最终用户向系统发出的一个请求的一部分。

我根据几个示例创建了一个过滤器,其中展示了如何将值设置到 MDC 中。例如(https://logback.qos.ch/manual/mdc.html1

...
@Component
public class RequestFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            String mdcData = String.format("[userId:%s | requestId:%s] ", user(), requestId());
            MDC.put("mdcData", mdcData); //Referenced from logging configuration.
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }

    private String requestId() {
        return UUID.randomUUID().toString();
    }

    private String user() {
        return "tux";
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}
...

如果我向休息服务发出请求,它会执​​行一次,而系统不会向自己发出任何额外的信息请求。这是我所期望的,我可以看到它们都包含相同 requestId 的日志条目。 如果我向我们的 Swagger 页面之一发出浏览器页面请求,则该网页会发出多个内部请求,以获取将出现在页面上的附加信息。由于对页面需要呈现的信息的所有附加请求,日志记录捕获了加载网页请求时发出的大约 20 个请求。发生这种情况时,我最终会得到 X 个日志条目,其中每个内部请求都生成一个唯一请求,并且 requestId 会为每个请求记录。这不是我的本意。

我如何确定向系统发出的请求中所创建的内部请求调用的发起部分?

我不需要一遍又一遍地为 requestId 设置 MDC 值。根据外部用户发出的第一个请求,我只需要在每次调用时设置一次。

除了请求的生命周期之外,我什至不确定你会称之为什么,但我没有找到答案。

感谢任何指导。谢谢。

编辑:链接到我那里的另一个问题,该问题仅处理识别original user request

【问题讨论】:

  • “子调用”是什么意思?你的意思是一个给定的请求被转发了很多次,并且每次转发都会调用过滤器?如果是这样,您可以只在请求中存储一个属性,如果该属性已设置,则避免过滤。您还可以设置过滤器的调度程序类型 (docs.oracle.com/javaee/7/api/javax/servlet/annotation/…)。如果这不是您所说的“子调用”,请解释一下。
  • 通过子调用,是的,系统正在对自身进行许多其他调用,这些调用正在触发过滤器。我检查了所有显示为请求的调度程序类型。我将研究属性的设置,这听起来可能是我需要的简单修复。
  • 目前还不清楚您所说的“系统”和“呼叫”是什么意思。如果您有一个前端向您的服务器发送许多请求,那么就没有“子调用”之类的东西。这些只是请求,彼此独立。
  • 我很抱歉。请允许我重写问题。

标签: java logback slf4j servlet-filters mdc


【解决方案1】:

解决此问题的一种方法是将 RequestFilter 映射到要记录的服务的 URL 模式,而不是“/*”。

编辑:另一个想法是将过滤器映射到“/*”,但在您的doFilter 方法中,不要对 URL 中包含“swagger”的任何请求进行 MDC。您可能需要尝试并可能包含从 Swagger 页面生成的所有 URL,因为其中一些可能不包含“swagger”一词。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    if (isRequestSwaggerUrl(request)) {
        chain.doFilter(request, response);
        return;
    }

    try {
        String mdcData = String.format("[userId:%s | requestId:%s] ", user(), requestId());
        MDC.put("mdcData", mdcData); //Referenced from logging configuration.
        chain.doFilter(request, response);
    } finally {
        MDC.clear();
    }
}

【讨论】:

  • 我试图避免这样做,因为我不知道系统以及所有可以加载的端点或页面,但如果我这样做,我将不得不这样做我不能更通用。感谢您的意见。
猜你喜欢
  • 2015-11-09
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
  • 2012-06-03
  • 2011-07-29
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
相关资源
最近更新 更多