Request Body
可以从 ReactiveAdapterRegistry
处理的任何异步类型对请求正文进行编码,如同以下示例所示:
-
Java
-
Kotlin
Mono<Person> personMono = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, Person.class)
.retrieve()
.bodyToMono(Void.class);
val personDeferred: Deferred<Person> = ...
client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body<Person>(personDeferred)
.retrieve()
.awaitBody<Unit>()
如以下示例所示,您也可以对对象的流进行编码:
-
Java
-
Kotlin
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);
val people: Flow<Person> = ...
client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(people)
.retrieve()
.awaitBody<Unit>()
或者,如果您有实际值,可以使用 bodyValue
快捷方法,如同以下示例所示:
-
Java
-
Kotlin
Person person = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.bodyToMono(Void.class);
val person: Person = ...
client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.awaitBody<Unit>()
Form Data
要发送表单数据,可以提供 MultiValueMap<String, String>
作为正文。请注意,内容由 FormHttpMessageWriter
自动设置为 application/x-www-form-urlencoded
。以下示例展示如何使用 MultiValueMap<String, String>
:
-
Java
-
Kotlin
MultiValueMap<String, String> formData = ... ;
Mono<Void> result = client.post()
.uri("/path", id)
.bodyValue(formData)
.retrieve()
.bodyToMono(Void.class);
val formData: MultiValueMap<String, String> = ...
client.post()
.uri("/path", id)
.bodyValue(formData)
.retrieve()
.awaitBody<Unit>()
如以下示例所示,您还可以使用 BodyInserters
内联提供表单数据:
-
Java
-
Kotlin
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);
import org.springframework.web.reactive.function.BodyInserters.*
client.post()
.uri("/path", id)
.body(fromFormData("k1", "v1").with("k2", "v2"))
.retrieve()
.awaitBody<Unit>()
Multipart Data
要发送多部分数据,您需要提供一个 MultiValueMap<String, ?>
,其值为表示部件内容的 Object
实例,或表示部件的内容和头的 HttpEntity
实例。MultipartBodyBuilder
提供了一个便捷的 API 来准备一个多部分请求。以下示例展示如何创建一个 MultiValueMap<String, ?>
:
-
Java
-
Kotlin
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 from a server request
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
val builder = MultipartBodyBuilder().apply {
part("fieldPart", "fieldValue")
part("filePart1", FileSystemResource("...logo.png"))
part("jsonPart", Person("Jason"))
part("myPart", part) // Part from a server request
}
val parts = builder.build()
在大多数情况下,您不必为每个部件指定 Content-Type
。内容类型会根据选择的 HttpMessageWriter
自动确定,序列化或在 Resource
的情况下,基于文件扩展名自动确定。如果需要,您可以通过一个重载的构建器 part
方法为每个部件明确提供要使用的 MediaType
。
准备 MultiValueMap
后,最简单的传递给 WebClient
的方式是通过 body
方法,如同以下示例所示:
-
Java
-
Kotlin
MultipartBodyBuilder builder = ...;
Mono<Void> result = client.post()
.uri("/path", id)
.body(builder.build())
.retrieve()
.bodyToMono(Void.class);
val builder: MultipartBodyBuilder = ...
client.post()
.uri("/path", id)
.body(builder.build())
.retrieve()
.awaitBody<Unit>()
如果 MultiValueMap
包含至少一个非 String
值(可能也表示常规表单数据(即 application/x-www-form-urlencoded
)),则无需将 Content-Type
设置为 multipart/form-data
。使用 MultipartBodyBuilder
时总是如此,它确保一个 HttpEntity
包装器。
与 MultipartBodyBuilder
作为替代方案,您也可以通过内置 BodyInserters
以内联样式提供多部分内容,如同以下示例所示:
-
Java
-
Kotlin
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);
import org.springframework.web.reactive.function.BodyInserters.*
client.post()
.uri("/path", id)
.body(fromMultipartData("fieldPart", "value").with("filePart", resource))
.retrieve()
.awaitBody<Unit>()
PartEvent
要顺序流式传输多部分数据,您可以通过 PartEvent
对象提供多部分内容。
-
可以通过 `FormPartEvent::create`创建表单字段。
-
可以通过 `FilePartEvent::create`创建文件上传。
您可以通过 Flux::concat
连接方法返回的流,并为 WebClient
创建一个请求。
例如,此示例将发布包含一个表单字段和一个文件的 multipart 表单。
-
Java
-
Kotlin
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);
var resource: Resource = ...
var result: Mono<String> = webClient
.post()
.uri("https://example.com")
.body(
Flux.concat(
FormPartEvent.create("field", "field value"),
FilePartEvent.create("file", resource)
)
)
.retrieve()
.bodyToMono()
在服务器端,通过 @RequestBody
或 ServerRequest::bodyToFlux(PartEvent.class)
收到的 PartEvent
对象可以通过 WebClient
中继到另一个服务。