請求體
請求體可以從 ReactiveAdapterRegistry 處理的任何非同步型別(如 Mono 或 Kotlin 協程的 Deferred)編碼,如下例所示
-
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>()
表單資料
要傳送表單資料,你可以提供一個 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>()
多部分資料
要傳送多部分資料,你需要提供一個 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 建立一個請求。
例如,此示例將 POST 一個包含表單欄位和檔案的多部分表單。
-
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 中繼到另一個服務。