Spring WebFlux 和 WebClient 调用不工作

问题描述 投票:0回答:1

我是反应式编程的新手,我有以下 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)
        
        }
        );
}
spring spring-boot spring-webflux project-reactor spring-webclient
1个回答
2
投票

这是切换到响应式编程后的常见错误之一。在你订阅之前,反应式不会发生任何事情。您需要使用

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));
}
© www.soinside.com 2019 - 2024. All rights reserved.