如何在 Spring WebClient 中拦截 http 流量?

Posted

技术标签:

【中文标题】如何在 Spring WebClient 中拦截 http 流量?【英文标题】:How to intercept http traffic in Spring WebClient? 【发布时间】:2019-11-21 02:10:49 【问题描述】:

WebFilter 请求从 DTO 转换为 JSON 字符串后如何拦截?

当然我可以添加一个ExchangeFilterFunction,但是clientRequest.body()只显示我的输入对象,而不是转换后的json字符串:

WebClient.builder().defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).filter(logRequest()).build();

private ExchangeFilterFunction logRequest() 
    return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> 
        LOGGER.info(clientRequest.body()); //body is MyRequest.class
        return Mono.just(clientRequest);
    );


MyRequestDto dto;
client.post().uri(url).syncBody(dto).retrieve().bodyToMono(MyResponseDto.class).block();

所以我正在寻找一种方法来拦截从 dto 转换为 json 字符串后的传出请求。

反之,在响应从 json 转换为 dto 之前拦截响应。

【问题讨论】:

【参考方案1】:

数据由 JacksonEncoder 以String 的形式写入,而是以DataBuffer 中的字节形式写入。拦截请求的一种方法是覆盖 JSON 编码器,并直接访问 DataBuffer 或将其解释为 String

Consumer<ClientCodecConfigurer> consumer = configurer ->
        configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder() 
            @Override
            public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) 
                return super.encode(inputStream, bufferFactory, elementType, mimeType, hints)
                        .doOnNext(dataBuffer -> System.out.println(StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer()).toString()));
            
        );

WebClient webClient = WebClient.builder()
        .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build())
        .build();

如果目的只是记录传出消息正文,请参阅此问题:how to log Spring 5 WebClient call

【讨论】:

关于您的链接答案:存在同样的问题:在 ExchangeFilterFunction 内部,正文已编码为 DTO,因此无法作为本机缓冲区访问。您能否添加一个示例,说明如何拦截响应缓冲区以将其写下来? 它在答案中;)它按预期打印 JSON 对于Jaxb2XmlDecoder?如何从Publisher&lt;DataBuffer&gt; inputStream 获取数据缓冲区? 你可以把Publisher转成Mono/Flux(例子在org.springframework.http.codec.xml.XmlEventDecoder#decode),然后做同样的事情。 对不起,对于我的问题,您的答案按预期工作!传出请求记录为 json/xml 字符串。问题更多在于正确拦截响应。也许你也可以看看? ***.com/questions/57037543/…

以上是关于如何在 Spring WebClient 中拦截 http 流量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring 响应式 WebClient 中返回 Kotlin Coroutines Flow

如何在运行在 Tomcat 上的 Spring Web 应用程序中使用 Spring 的响应式 WebClient

如何使用Spring WebClient同时进行多个调用?

如何在 Spring Webflux / WebClient 中设置事件循环池大小?

Spring WebClient:如何将大字节 [] 流式传输到文件?

Spring 5 webflux如何在Webclient上设置超时