同步使用
WebClient 可以通过在最后阻塞的方式来以同步方式使用以获取结果:
- Java
- Kotlin
Person person = client.get().uri("/person/{id}", i).retrieve()
.bodyToMono(Person.class)
.block();
List<Person> persons = client.get().uri("/persons").retrieve()
.bodyToFlux(Person.class)
.collectList()
.block();
val person = runBlocking {
client.get().uri("/person/{id}", i).retrieve()
.awaitBody<Person>()
}
val persons = runBlocking {
client.get().uri("/persons").retrieve()
.bodyToFlow<Person>()
.toList()
}
然而,如果需要多次调用,避免在每次响应时都进行阻塞,而是等待综合结果会更为高效:
- Java
- Kotlin
Mono<Person> personMono = client.get().uri("/person/{id}", personId)
.retrieve().bodyToMono(Person.class);
Mono<List<Hobby>> hobbiesMono = client.get().uri("/person/{id}/hobbies", personId)
.retrieve().bodyToFlux(Hobby.class).collectList();
Map<String, Object> data = Mono.zip(personMono, hobbiesMono, (person, hobbies) -> {
Map<String, String> map = new LinkedHashMap<>();
map.put("person", person);
map.put("hobbies", hobbies);
return map;
})
.block();
val data = runBlocking {
val personDeferred = async {
client.get().uri("/person/{id}", personId)
.retrieve().awaitBody<Person>()
}
val hobbiesDeferred = async {
client.get().uri("/person/{id}/hobbies", personId)
.retrieve().bodyToFlow<Hobby>().toList()
}
mapOf("person" to personDeferred.await(), "hobbies" to hobbiesDeferred.await())
}
以上只是一个例子。还有很多其他的模式和操作符可以用来构建一个反应式管道(reactive pipeline),这种管道会进行多次远程调用,其中可能还有一些嵌套的、相互依赖的调用,而且在整个流程结束之前,都不会有任何阻塞现象。
备注
使用 Flux 或 Mono 时,你根本不必在 Spring MVC 或 Spring WebFlux 控制器中进行阻塞操作。只需从控制器方法中返回相应的反应式类型即可。这一原则同样适用于 Kotlin 协程(Kotlin Coroutines)和 Spring WebFlux,只需在控制器方法中使用挂起函数(suspending functions)或返回 Flow 对象即可。