doc: 阅读webclient文档
This commit is contained in:
@@ -233,3 +233,165 @@ Mono<Person> result = client.get()
|
||||
.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