【问题标题】:How to log RequestBody in async spring controller?如何在异步弹簧控制器中记录 RequestBody?
【发布时间】:2020-04-01 08:55:54
【问题描述】:

我向现有的spring-mvc 应用程序添加了一个异步端点:

@RestController
public class MyController {
    @PostMapping("/")
    public Mono<String> post(Object body) {
       return Mono.just("test");
       //webClient.retrieve().bodyToMono(String.class);
    }
}

我想创建一个全局拦截器/过滤器来记录请求正文有效负载。但是我怎样才能访问它呢?

我尝试添加HandlerInterceptorAdapter,但有效负载始终为空:

static class LoggingInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(request);
            byte[] buf = wrapper.getContentAsByteArray();
            System.out.println(buf);
            System.out.println(buf.length);

            return true;
        }
}

可能负载尚未出现在请求中,或者已被读取。那么在这种异步情况下如何访问正文?

【问题讨论】:

  • 使用IOUtils.toString(request.getReader())获取请求正文内容,不知道我们的代码有什么不同?

标签: java spring spring-mvc spring-webflux spring-reactive


【解决方案1】:

不幸的是,在 Webflux 中您不能使用 HandlerInterceptorAdapter,因为它来自 web mvc 模块并且仅适用于 servlet。 我找到了一篇不错的文章,solutions

附:如果要使用响应式端点,您必须删除 spring-mvc 依赖项。

【讨论】:

  • 不幸的是我不得不保留spring-mvc。
  • 所以,对于 web mvc 中的异步端点,使用 @Async 注释而不使用 webflux
  • 好的,但在我的真实世界应用程序中,我直接从webClient 调用返回一个Mono&lt;String&gt;,所以我必须在这里返回一个Mono(或在网络客户端上使用.block() ,这不好)。
  • 不要使用 RestTemplate,它已被弃用。你应该使用 WebClient,如果你想像 RestTemplate 一样使用 WebClient,你可以调用 block(),它的行为方式和 restTemplate 一样。
  • 如果你有一个将 Mono/Flux 返回给调用客户端的 rest 端点,那么阻塞在完整的 webflux 应用程序中是不好的,那么阻塞是不好的。反应式应用程序不一定是“异步”的。所以说“异步弹簧控制器”是错误的。如果应用程序认为应该同步处理请求,则反应式应用程序可以是“同步的”。
猜你喜欢
  • 1970-01-01
  • 2020-05-26
  • 2014-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多