Spring Framework中WebClient请求体处理详解
spring-framework 项目地址: https://gitcode.com/gh_mirrors/spr/spring-framework
前言
在Spring WebFlux中,WebClient是进行响应式HTTP请求的核心组件。本文将深入探讨如何使用WebClient处理不同类型的请求体,包括JSON数据、表单数据和多部分数据。
基本请求体处理
1. 单一对象请求体
WebClient支持通过Mono
或Kotlin的Deferred
发送异步请求体:
// Java示例
Mono<Person> personMono = ...;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, Person.class)
.retrieve()
.bodyToMono(Void.class);
// Kotlin示例
val personDeferred: Deferred<Person> = ...
client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body<Person>(personDeferred)
.retrieve()
.awaitBody<Unit>()
2. 流式对象请求体
对于流式数据,可以使用Flux
(Java)或Flow
(Kotlin):
// Java示例
Flux<Person> personFlux = ...;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_STREAM_JSON)
.body(personFlux, Person.class)
.retrieve()
.bodyToMono(Void.class);
3. 直接值请求体
如果已经有具体的值,可以使用更简洁的bodyValue
方法:
// Java示例
Person person = ...;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.bodyToMono(Void.class);
表单数据处理
1. 使用MultiValueMap
表单数据通常使用MultiValueMap<String, String>
表示,内容类型会自动设置为application/x-www-form-urlencoded
:
// Java示例
MultiValueMap<String, String> formData = ...;
Mono<Void> result = client.post()
.uri("/path", id)
.bodyValue(formData)
.retrieve()
.bodyToMono(Void.class);
2. 使用BodyInserters内联构建
也可以使用BodyInserters
工具类内联构建表单数据:
// Java示例
import static org.springframework.web.reactive.function.BodyInserters.*;
Mono<Void> result = client.post()
.uri("/path", id)
.body(fromFormData("k1", "v1").with("k2", "v2"))
.retrieve()
.bodyToMono(Void.class);
多部分数据处理
1. 使用MultipartBodyBuilder
MultipartBodyBuilder
提供了构建多部分请求的便捷API:
// Java示例
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("fieldPart", "fieldValue");
builder.part("filePart1", new FileSystemResource("...logo.png"));
builder.part("jsonPart", new Person("Jason"));
builder.part("myPart", part); // 来自服务器请求的Part
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
构建完成后,可以这样使用:
MultipartBodyBuilder builder = ...;
Mono<Void> result = client.post()
.uri("/path", id)
.body(builder.build())
.retrieve()
.bodyToMono(Void.class);
2. 使用BodyInserters内联构建
同样可以使用BodyInserters
工具类内联构建多部分数据:
import static org.springframework.web.reactive.function.BodyInserters.*;
Mono<Void> result = client.post()
.uri("/path", id)
.body(fromMultipartData("fieldPart", "value").with("filePart", resource))
.retrieve()
.bodyToMono(Void.class);
使用PartEvent流式传输多部分数据
Spring Framework 5.3引入了PartEvent
API,用于流式处理多部分数据:
// Java示例
Resource resource = ...
Mono<String> result = webClient
.post()
.uri("https://example.com")
.body(Flux.concat(
FormPartEvent.create("field", "field value"),
FilePartEvent.create("file", resource)
), PartEvent.class)
.retrieve()
.bodyToMono(String.class);
PartEvent
的主要优点:
- 可以流式处理大型文件,避免内存溢出
- 支持顺序组合多个部分
- 服务器端接收后可以直接转发到其他服务
最佳实践
- 内容类型处理:大多数情况下,Spring会根据内容自动设置合适的Content-Type,但必要时可以显式指定
- 资源处理:对于文件资源,Spring会根据文件扩展名自动推断内容类型
- 内存考虑:处理大型文件时,优先考虑使用流式API如
PartEvent
- 错误处理:记得为所有响应式操作添加适当的错误处理
总结
Spring WebClient提供了灵活多样的请求体处理方式,从简单的JSON对象到复杂的多部分表单数据,都能优雅处理。理解这些不同的处理方式,可以帮助开发者根据具体场景选择最合适的API,构建高效可靠的HTTP客户端应用。
spring-framework 项目地址: https://gitcode.com/gh_mirrors/spr/spring-framework
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考