跳到主要内容
版本:7.0.3

请求体

Hunyuan 7b 中英对照 Request Body

请求体可以由ReactiveAdapterRegistry处理的任何异步类型进行编码,例如Mono或Kotlin协程中的Deferred,如下例所示:

Mono<Person> personMono = ... ;

Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, Person.class)
.retrieve()
.bodyToMono(Void.class);

如下例所示,你也可以对对象流进行编码:

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);

或者,如果你有实际值,你可以使用bodyValue快捷方法,如下例所示:

Person person = ... ;

Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.bodyToMono(Void.class);

表单数据

要发送表单数据,你可以提供一个 MultiValueMap<String, String> 作为请求体。请注意,FormHttpMessageWriter 会自动将内容设置为 application/x-www-form-urlencoded 格式。以下示例展示了如何使用 MultiValueMap<String, String>

MultiValueMap<String, String> formData = ... ;

Mono<Void> result = client.post()
.uri("/path", id)
.bodyValue(formData)
.retrieve()
.bodyToMono(Void.class);

您也可以使用BodyInserters内联提供表单数据,如下例所示:

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);

多部分数据

要发送多部分数据,你需要提供一个MultiValueMap<String, ?>,其值要么是表示部分内容的Object实例,要么是表示部分内容和头的HttpEntity实例。MultipartBodyBuilder提供了一个便捷的API来准备多部分请求。以下示例展示了如何创建一个MultiValueMap<String, ?>

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();

在大多数情况下,你不必为每个部分指定Content-Type。内容类型会根据所选择的HttpMessageWriter自动确定,或者对于Resource来说,是根据文件扩展名来确定的。如有必要,你可以通过其中一个重载的part方法显式提供用于每个部分的MediaType

一旦准备好了MultiValueMap,将其传递给WebClient的最简单方法是通过body方法,如下例所示:

MultipartBodyBuilder builder = ...;

Mono<Void> result = client.post()
.uri("/path", id)
.body(builder.build())
.retrieve()
.bodyToMono(Void.class);

如果MultiValueMap中至少包含一个非String类型的值,而这些值也可能代表常规表单数据(即application/x-www-form-urlencoded格式),则无需将Content-Type设置为multipart/form-data。在使用MultipartBodyBuilder时总是如此,因为MultipartBodyBuilder会确保生成一个HttpEntity包装器。

作为MultipartBodyBuilder的替代方案,你也可以通过内置的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

要顺序流式传输多部分数据,您可以通过PartEvent对象提供多部分内容。

  • 可以通过 FormPartEvent::create 创建表单字段。
  • 可以通过 FilePartEvent::create 创建文件上传功能。

你可以使用Flux::concat来连接方法返回的流(streams),然后为WebClient创建一个请求。

例如,这个示例将发送一个包含表单字段和文件的多部分(multipart)表单数据。

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);

在服务器端,通过@RequestBodyServerRequest::bodyToFlux(PartEvent.class)接收到的PartEvent对象可以通过WebClient转发给另一个服务。