WebClient请求的简单日志转储?

时间:2020-06-07 06:03:03

标签: spring webclient

我正在尝试使用Spring WebClient进行一些基本的REST API调用。我收到请求格式错误的错误,但我无法确切说明原因。有什么方法可以轻松记录请求的内容(真的,只是请求正文)吗?我在网上找到的所有内容都非常复杂。这就是我所拥有的:

LinkedMultiValueMap params = new LinkedMultiValueMap();
params.add("app_id", getOneSignalAppId());
params.add("included_segments", inSegment);
params.add("content_available", true);
params.add("contents", new LinkedMultiValueMap() {{
                            add("en", inTitle);
                        }});

BodyInserters.MultipartInserter inserter = BodyInserters.fromMultipartData(params);

WebClient client = WebClient.builder()
                                .baseUrl("https://onesignal.com")
                                .defaultHeader(HttpHeaders.AUTHORIZATION, "Basic " + getOneSignalKey())
                                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                                .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
                            .build();
Mono<NotificationResponse> result = client
                                .post()
                                .uri("/api/v1/notifications")
                                .body(inserter)
                                .retrieve()
                                .bodyToMono(NotificationResponse.class);

我只想要将插入到请求正文中的JSON字符串。

1 个答案:

答案 0 :(得分:0)

您可以围绕JSON编码器创建自己的包装器/代理类(假设您使用的是JSON),并在将序列化的正文发送到插管之前对其进行拦截。

如果您的请求将发送JSON。 具体来说,您将扩展encodeValue(默认编码器)的encodeValues方法(或在流数据的情况下为Jackson2JsonEncoder)。然后,您可以根据需要处理这些数据,例如日志记录等。甚至可以根据环境/配置文件有条件地进行处理。

可以在创建WebClient时通过将其提供为编解码器来指定此自定义日志记录编码器:

 CustomBodyLoggingEncoder bodyLoggingEncoder = new CustomBodyLoggingEncoder();
 WebClient.builder()
          .codecs(clientDefaultCodecsConfigurer -> {
             clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(bodyLoggingEncoder);
             clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
          })
          ...

我对此做了blog post。您也许可以找到用于Multipart数据的编码器并应用类似的原理

为完整起见,编码器可能看起来像这样:

public class CustomBodyLoggingEncoder extends Jackson2JsonEncoder {
    @Override
    public DataBuffer encodeValue(final Object value, final DataBufferFactory bufferFactory,
                                  final ResolvableType valueType, @Nullable final MimeType mimeType, @Nullable final Map<String, Object> hints) {

        // Encode/Serialize data to JSON
        final DataBuffer data = super.encodeValue(value, bufferFactory, valueType, mimeType, hints);

        // This is your code:
        SomethingAmazing.doItWithThisData(extractBytes(data));

        // Return the data as normal
        return data;
    }

    private byte[] extractBytes(final DataBuffer data) {
        final byte[] bytes = new byte[data.readableByteCount()];
        data.read(bytes);
        // We've copied the data above to our array, but must reset the buffer for actual usage
        data.readPosition(0);
        return bytes;
    }
}

希望能有所帮助!