spring - 如何使用 WebClient 压缩 JSON 请求正文?
问题描述
我需要POST
使用WebClient
,并且服务器需要压缩主体。我已经检查了以前在这里和这里提出的问题,但没有一个帮助我了解需要做什么。
我的代码看起来像这样:
webClient.post()
.bodyValue(requestBody)
.retrieve()
.bodyToMono(Response.class)
我想requestBody
使用 gzip 发送压缩文件。我们是用 RestTemplate 和一个自定义来做的,GZipFilter
但我现在看不到如何用 WebClient 来做。
解决方案
我已经实现了示例代码来帮助您解决这个问题。您将需要清理它并适应您的需求,但我已经对此进行了测试并且它确实有效。
第一步是实现Encoder<T>
where<T>
是您要编码的对象的类型。在我的示例中,我使用的是 JsonNode。
public class GzipEncoder extends AbstractEncoder<JsonNode> {
public GzipEncoder() {
super(MediaType.APPLICATION_JSON);
}
@Override
public boolean canEncode(ResolvableType elementType, MimeType mimeType) {
return MediaType.APPLICATION_JSON.equalsTypeAndSubtype(mimeType) && elementType.isAssignableFrom(JsonNode.class);
}
@Override
public Flux<DataBuffer> encode(Publisher<? extends JsonNode> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
return Flux.from(inputStream).map((JsonNode node) ->
encodeValue(node, bufferFactory, elementType, mimeType, hints));
}
@Override
public DataBuffer encodeValue(JsonNode node, DataBufferFactory bufferFactory, ResolvableType valueType, MimeType mimeType, Map<String, Object> hints) {
return bufferFactory.wrap(gzip(node.toString()));
}
private byte[] gzip(String value) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
gzipOutputStream.write(value.getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
return baos.toByteArray();
}
}
然后你还必须实现一个HttpMessageWriter
public class GzipHttpMessageWriter extends EncoderHttpMessageWriter {
public GzipHttpMessageWriter() {
super(new GzipEncoder());
}
@Override
public Mono<Void> write(Publisher inputStream, ResolvableType elementType, MediaType mediaType, ReactiveHttpOutputMessage message, Map hints) {
return super.write(inputStream, elementType, mediaType, updateContentEncoding(message), hints);
}
private ReactiveHttpOutputMessage updateContentEncoding(ReactiveHttpOutputMessage message) {
message.getHeaders().add("Content-Encoding", "gzip");
return message;
}
}
现在创建WebClient
如下(我添加了窃听以确认 gzip 正在工作)
WebClient webclientGzip = WebClient.builder()
.codecs(clientCodecConfigurer -> clientCodecConfigurer.customCodecs().register(new GzipHttpMessageWriter()))
.clientConnector(new ReactorClientHttpConnector(HttpClient.create().wiretap(true)))
.build();
现在,当我发布一个带有以下内容的 JsonNode 主体时,我可以看到使用 gzip 编码的请求发出
webclientGzip.post().uri(uri)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(body), JsonNode.class)
推荐阅读
- java - 如何修复 java.io.IOException: write failed: EPIPE (Broken pipe) 当我扎根时?
- qt - 使用 QML 显示视频预览/视频缩略图
- java - 如何从 Renderer 类 Opengles (android, java) 中访问文件
- vim - 使用 vim 选择 xml 块的最佳方法是什么?
- node.js - JWT 和 CSRF 令牌工作流程
- google-cloud-bigtable - 是否可以将 bigtable 请求写入特定区域?
- java - 我的 Spring Boot 微服务项目的 POM 不会停止显示父错误
- c++ - QVideoWidget 不显示帧
- wordpress - 谷歌索引显示 Wordpress 默认 favicon 而不是 set favicon
- django - 如何创建具有包含来自另一个模型中的字段的唯一值的字段的模型?