【问题标题】:How to implement/migrate OncePerRequestFilter using Spring webflux如何使用 Spring webflux 实现/迁移 OncePerRequestFilter
【发布时间】:2023-04-01 05:20:02
【问题描述】:

使用 Spring web 一个简单的OncePerRequestFilter(见下文)可以为请求的跨度维护一个请求 ID。 将生成的请求 ID 存储在请求属性中,将其添加到日志记录 MDC,并在响应标头中返回。

我知道响应式 webflux 堆栈是完全不同的,那么应该如何解决这个问题?

我找到了https://github.com/spring-projects/spring-framework/issues/20239,但不清楚现在支持与否。

@Component
public class RequestIdFilter extends OncePerRequestFilter implements Ordered {

    private static final String MDC_KEY = "requestId";
    private static final String REQUEST_ATTRIBUTE_NAME = "requestId";
    private static final String RESPONSE_HEADER_NAME = "X-Request-Id";


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        var requestId = UUID.randomUUID().toString();
        MDC.put(MDC_KEY, requestId);
        request.setAttribute(REQUEST_ATTRIBUTE_NAME, requestId);
        response.setHeader(RESPONSE_HEADER_NAME, requestId);
        try {
            filterChain.doFilter(request, response);
        } finally {
            MDC.remove(MDC_KEY);
        }
    }

    @Override
    public int getOrder() {
        return requestIdProperties.getServerFilterOrder();
    }
}

【问题讨论】:

    标签: spring spring-boot spring-webflux


    【解决方案1】:

    您不需要在 WebFlux 中实现 OncePerRequestFilter,因为过滤器只执行一次,因为 WebFlux 不支持请求转发(如在 Servlet 中)。

    现在您可以实现一个WebFilter,它将 requestId 添加为请求属性,与您显示的版本非常相似。

    有几点需要注意:

    • 你应该避免在你的反应式管道中调用阻塞方法,UUID.randomUUID()is blocking
    • 在反应式环境中向 MDC 添加数据并不简单,因为此功能最初依赖于ThreadLocal。立即查看this blog post 并关注this issue for more guidance
    • 考虑到这个用例,听起来Spring Cloud Sleuth 可能会实现您想要的,甚至更多(支持跨度等)。

    【讨论】:

      猜你喜欢
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2018-06-30
      相关资源
      最近更新 更多