doc: 阅读webclient文档
This commit is contained in:
@@ -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();
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user