我是反应式编程的新手,我有以下 rest 资源调用使用 WebClient 调用现有 Rest API 的服务:
@PostMapping
public Mono<String> createUser(@RequestBody UserResourceDTO userResourceDto) {
return userService.createUser(userResourceDto);
}
在我的服务中,我有以下方法可以正常工作:
// Working method
public Mono<String> createUser(UserResourceDTO userResourceDTO){
return httpCall(userResourceDTO);
}
当我使用此方法时,将触发 HTTP 调用并在我的日志中看到它,但由于我不想从此方法返回值,因此我尝试了以下方法:
// Not Working method
public Mono<String> createUser(UserResourceDTO userResourceDTO){
Mono<String> rs = httpCall(userResourceDTO);
return Mono.just("just a value");
// i plan to trigger another call to the DB this is why i don't want to return the result from httpCall
// return userRepository.createUser(userResourceDTO);
}
此方法不起作用并且未触发 HTTP 请求(我没有像第一种方法那样在控制台中看到它),任何人都可以向我解释为什么第二种方法没有触发 WebClient 调用以及为什么我有义务从
mhttpCall(userResourceDTO);
返回结果
这是http调用代码:
public Mono<String> httpCall(UserResourceDTO userResourceDTO) {
WebClient webClient = WebClient.create();
KeyCloakUser keyCloakUser = new KeyCloakUser();
// setting values...
return webClient.post()
.uri(new URI("myurl"))
.header("Authorization", "Bearer "+toremove)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.body(Mono.just(keyCloakUser), KeyCloakUser.class)
.retrieve()
.bodyToMono(String.class);
}
// method with a second call not triggerd
public Mono<UserResourceDTO> twocalls(UserResourceDTO userResourceDTO){
return httpCall(userResourceDTO)
.flatMap(res -> {
// Sysout not executed
System.out.println(res);
// my API return empty body with 201
if("".equals(res)
return userRepository.createUser(userResourceDTO)
}
);
}
这是切换到响应式编程后的常见错误之一。在你订阅之前,反应式不会发生任何事情。您需要使用
flatMap
、map
等反应运算符来链接异步/同步函数
理解这个概念的良好起点是Flux 1的飞行-组装与订阅。
不正确
public Mono<String> createUser(UserResourceDTO userResourceDTO){
Mono<String> rs = httpCall(userResourceDTO);
return Mono.just("just a value");
}
httpCall(userResourceDTO)
不会作为反应流的一部分执行。
正确
public Mono<String> createUser(UserResourceDTO userResourceDTO){
return httpCall(userResourceDTO)
.then(Mono.just("just a value"));
}
继续另一个异步调用
public Mono<String> createUser(UserResourceDTO userResourceDTO){
return httpCall(userResourceDTO)
.then(userRepository.createUser(userResourceDTO));
}
或者,如果您需要 HTTP 调用的结果
public Mono<String> createUser(UserResourceDTO userResourceDTO){
return httpCall(userResourceDTO)
.flatMap(res -> userRepository.createUser(userResourceDTO));
}