spring - WebClient 请求的简单日志转储?
问题描述
我正在尝试使用 SpringWebClient
进行一些基本的 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 字符串。
解决方案
您可以围绕 JSON 编码器创建自己的包装器/代理类(假设您使用的是 JSON)并在将序列化主体发送到 intertubes 之前拦截它。
如果您的请求要发送 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));
})
...
我为此写了一篇博文。您也许可以找到 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;
}
}
希望能有所帮助!
推荐阅读
- mongodb - 如何在mongodb项目中设置空字符串嵌套数组
- javascript - tsconfig.json中增量是什么意思?
- c++ - C++ 函数返回 0 而不是 0.35
- reinforcement-learning - 为什么我的代理在 DQN 中总是采取相同的操作 - 强化学习
- operating-system - 如何开始在智能卡中开发操作系统
- javascript - 如何以表格形式获取 axios 发布请求响应
- php - 将逗号分隔的字符串分隔为整数值
- python - 使用python循环调用多个SQL数据库
- node.js - 尝试使用 map() 解决 API 的 Promise
- mongodb - 使用 MongoDB 字段作为另一个值的键引用