doc: 阅读webclient文档

This commit is contained in:
asahi
2025-05-24 21:29:26 +08:00
parent 1eea88ccb8
commit 4b03f8d44e

View File

@@ -233,3 +233,165 @@ Mono<Person> result = client.get()
.bodyToMono(Person.class); .bodyToMono(Person.class);
``` ```
## Exchange
`exchangeToMono`方法和`exchangeToFlux`方法可以提供更精确的控制例如在statusCode不同时使用不同的方法来进行反序列化
```java
Mono<Person> entityMono = client.get()
.uri("/persons/1")
.accept(MediaType.APPLICATION_JSON)
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(Person.class);
}
else {
// Turn to error
return response.createError();
}
});
```
如上所示,当`exchangeToMono() and exchangeToFlux()`返回的flux或mono完成时clientResponse对象将会被释放从而避免内存和连接的泄露。
因而,`response`不能在更下游进行反序列化,`具体的反序列化过程由提供的方法来声明如何进行decode`
## Request Body
对于webclient可以加载任意异步类型对象到request body例如`Mono`
```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);
```
同样的,也可以加载多个异步对象,例如`Flux`类型
```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);
```
当不想从异步类型的对象加载值,而是想加载已有的值时,可以使用`bodyValue`方法:
```java
Person person = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.bodyToMono(Void.class);
```
### Form Data
如果想要发送form data可以为body指定`MultiValueMap<String, String>`类型的值content会被自动设置为`application/x-www-form-urlencoded`。使用示例如下所示:
```java
MultiValueMap<String, String> formData = ... ;
Mono<Void> result = client.post()
.uri("/path", id)
.bodyValue(formData)
.retrieve()
.bodyToMono(Void.class);
```
同时,可以使用`BodyInserters`来构建form data示例如下所示
```java
Mono<Void> result = client.post()
.uri("/path", id)
.body(fromFormData("k1", "v1").with("k2", "v2"))
.retrieve()
.bodyToMono(Void.class);
```
### Multipart Data
为了发送multipart data需要提供`MultiValueMap<String, ?>`类型的值其中value类型为`代表part内容的object对象``代表part内容和headers的HttpEntity对象`
`MutlipartBodyBuilder`提供了便捷的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 from a server request
MultiValueMap<String, HttpEntity<?>> parts = builder.build();
```
通常情况下无需为每个part指定`Content-Type`,在`HttpMessageWriter`执行序列化操作时会自动的设置ContentType类型对于`Resources`类型会根据文件拓展名来决定ContentType。
`MutliValueMap`类型的值构建完成后,使用示例如下:
```java
MultipartBodyBuilder builder = ...;
Mono<Void> result = client.post()
.uri("/path", id)
.body(builder.build())
.retrieve()
.bodyToMono(Void.class);
```
除了使用`MultipartBodyBuilder`之外,还可以使用`BodyInserters`来构建multipart body示例如下
```java
Mono<Void> result = client.post()
.uri("/path", id)
.body(fromMultipartData("fieldPart", "value").with("filePart", resource))
.retrieve()
.bodyToMono(Void.class);
```
### PartEvent
如果需要提供多个multipart data可以使用`PartEvent`类型:
- form fields可以通过`FormPartEvent::create`来创建
- file uploads可以通过`FormPartEvent::create`来创建
可以通过`Flux.concat`方法来对其进行拼接,示例如下所示:
```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);
```
## Filters
可以通过`WebClient.Builder`注册client filter其可以针对请求进行拦截和修改示例如下所示
```java
WebClient client = WebClient.builder()
.filter((request, next) -> {
ClientRequest filtered = ClientRequest.from(request)
.header("foo", "bar")
.build();
return next.exchange(filtered);
})
.build();
```
其可被用作认证,示例如下:
```java
WebClient client = WebClient.builder()
.filter(basicAuthentication("user", "password"))
.build();
```
通过修改WebClient对象filter可被添加和删除修改后的新webClient对象并不会影响之前的对象示例如下
```java
WebClient client = webClient.mutate()
.filters(filterList -> {
filterList.add(0, basicAuthentication("user", "password"));
})
.build();
```