【问题标题】:How to handle response before commit in Spring boot FilterHandlerFunction如何在 Spring Boot FilterHandlerFunction 中处理提交前的响应
【发布时间】:2018-03-04 11:41:29
【问题描述】:

我们正在将旧的 Spring 应用程序迁移到 Spring Boot 2.0。

目前我们有一个拦截器,它作为链中的第一个执行并执行以下操作:

  • ThreadLocal 中设置唯一ID
  • 在提交响应之前,从本地线程中删除唯一 ID。

我正在尝试找出一种在 Spring WebFlux 中实现这一点的方法。我可以使用WebFilter 实现来做到这一点;然而,由于我使用RouterFunction 作为控制器,我试图检查是否有办法通过HandlerFilterFunction 实现这一点。

public class TxIdFilter implements HandlerFilterFunction<ServerResponse, ServerResponse> {
  /**
   * {@inheritDoc}
   */
  @Override
  public Mono<ServerResponse> filter(ServerRequest request, HandlerFunction<ServerResponse> next) {
    /*
     * How to achieve following (which can be done
     * using WebFilter)
     * 
     * exchange.getResponse().beforeCommit(() -> {
     *   logger.debug("Cleaning up the tx id...");
     *   AppTransactionContext.removeAll();
     *   return Mono.empty();
     * });
     */
    return next.handle(request);
  }
}

【问题讨论】:

    标签: java spring-boot spring-webflux


    【解决方案1】:

    您可以这样做,尽管我在这里使用请求属性:

    public class SampleFilterFunction implements HandlerFilterFunction {
    
        @Override
        public Mono filter(ServerRequest request, HandlerFunction next) {
            request.attributes().put("key", "value");
            return next.handle(request)
                    .doOnSuccessOrError((value, error) -> request.attributes().remove("key"));
        }
    }
    

    您不应该在这里依赖ThreadLocal,因为与Servlet Spring MVC 模型不同,请求不绑定到特定线程。请求处理可以在任何给定时间跳到不同的线程。

    Reactor provides a Context API for those uses cases.

    根据您的实际用例(我不确定此事务 ID 在这里可能意味着什么),您还可以查看 Spring Cloud SleuthMicrometer 以及它们如何在各自的用例中解决该问题.

    【讨论】:

    • 谢谢布赖恩;我最终使用了doFinally 并且有效。关于 tx id,每当请求到达我们的应用程序时,我们想要设置一个 id,然后将其传递给所有层(dao、服务等),然后在响应提交之前,我们删除该 id。这就是我们使用过滤器的原因。我完全同意你的观点;但不太确定如何在反应式应用程序中实现它(甚至使用 Context API)。还有更多帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2012-04-22
    • 2015-05-24
    • 1970-01-01
    • 2018-10-10
    • 2017-07-14
    • 2023-02-17
    • 1970-01-01
    相关资源
    最近更新 更多