首页 > 解决方案 > Spring-webflux 过滤器获取请求正文

问题描述

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

@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;
    }
}

标签: springfilternonblockingspring-webfluxreactive

解决方案


因为您没有订阅,所以控制台上没有打印任何内容decodedRequest ,因为我们知道 Reactive 方面之一:

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

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

那么,如何解决呢?

  1. 创建您自己的包装器ServerWebExchange(请在此处阅读:如何在 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;
}

推荐阅读