Spring-webflux过滤器获取请求主体

时间:2019-03-01 05:47:50

标签: spring filter nonblocking spring-webflux reactive

我需要在过滤器中获取整个请求正文并将其转换为String。下面是我的代码,但控制台上没有任何内容。

@Component
public class WebFilter01 implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, 
      WebFilterChain webFilterChain) {    

        Flux<DataBuffer> requestBody = serverWebExchange.getRequest().getBody();        

        Flux<String> decodedRequest = requestBody.map(databuffer -> {
            return decodeDataBuffer(databuffer);
        });     
        decodedRequest.doOnNext(s -> System.out.print(s));
        return webFilterChain.filter(serverWebExchange);
    }


    protected String decodeDataBuffer(DataBuffer dataBuffer) {
        Charset charset = StandardCharsets.UTF_8;       
        CharBuffer charBuffer = charset.decode(dataBuffer.asByteBuffer());      
        DataBufferUtils.release(dataBuffer);        
        String value = charBuffer.toString();
        return value;
    }
}

1 个答案:

答案 0 :(得分:1)

由于您未订阅decodedRequest,因此在控制台上没有打印任何内容, 我们知道反应性方面之一:

  

在您订阅之前什么都不会发生

但是,如果这样做,您将在控制台上看到打印的正文,但是您的代码将不起作用,因为下一个操作员无法读取正文,您将获得IllegalStateException只有一个连接允许订阅者。

那么,如何解决呢?

  1. ServerWebExchange创建自己的包装器(请在此处阅读:How to log request and response bodies in Spring WebFlux
  2. HttpMessageDecoder中记录正文。例如,如果您看到AbstractJackson2Decoder,则会在 Spring 解码的缓冲区中找到对象并可以记录的代码:

    try { Object value = reader.readValue(tokenBuffer.asParser(getObjectMapper())); if (!Hints.isLoggingSuppressed(hints)) { LogFormatUtils.traceDebug(logger, traceOn -> { String formatted = LogFormatUtils.formatValue(value, !traceOn); return Hints.getLogPrefix(hints) + "Decoded [" + formatted + "]"; }); } return value; }