繁体   English   中英

需要帮助理解反应式 Mono/Flux 类

[英]Need help understanding reactive Mono/Flux classes

我正在编写一个 Java 应用程序并尝试使用 Spring WebFlux WebClient来调用 REST API。 我刚开始使用这个库,几乎没有“反应式”编程的经验。 我很难理解MonoFlux类是如何工作和使用的。 在这一点上我了解的很少,这些类允许对某种数据源(例如远程 Web 服务)进行异步操作。 WebFlux 中的一切似乎都处理MonoFlux对象。

在这一点上,我最大的问题/困惑是,如果它们允许异步处理,我们如何在异步进程和启动它的进程之间架起桥梁? 我最近(大约 10 年前)对此类处理的经验涉及ExecutorFuture 我也花了一些时间来掌握这些。 (我也忘记了很多。)

这是我编写的一些代码,试图帮助说明我的意思。

@Service
public class GitLabService2 {
  @Autowired
  private WebClient     webClient;
    
  public Flux<String> getGroupByName(String name) {
    Flux<String> result = webClient.get()
      .uri("/groups?search=" + name)
      .accept(MediaType.APPLICATION_JSON)
      .exchangeToFlux(resp -> {
        if (!resp.statusCode().isError()) {
          return resp.bodyToFlux(String.class);
        } else {
          return resp.createException().flatMapMany(Flux::error);
        }
      });
    
    return result;
  }

  public Flux<String> getAllProjectsForGroup(String name) {
    Flux<String> gf = getGroupByName(name);
    int groupID = 0;
    
    gf.subscribe(json -> {
      if (JacksonJsonConverter.isList(json)) {
        List<JsonNode> list = JacksonJsonConverter.convertToObjectList(json);
        // This is the ID of the group I need to use below. However, I can't get it out of this lambda.
        // (Getting info out of lambdas is a separate topic that keeps causing me pain.)
        int groupID = list.get(0).get("id").asInt(); 
      }
    });
    
    Flux<String> result = webClient.get()
      // This is where I need to use the groupID I get above, but can't access it.
      .uri("/groups/" + groupID + "/projects")
      .accept(MediaType.APPLICATION_JSON)
      .exchangeToFlux(resp -> {
        if (!resp.statusCode().isError()) {
          return resp.bodyToFlux(String.class);
        } else {
          return resp.createException().flatMapMany(Flux::error);
        }
      });
    
    return result;
  }
    
}

这是使用上述代码的代码。

  private void getAllProjectsForGroup() {
    Flux<String> result = service.getAllProjectsForGroup("test");

    result.subscribe(jsonStr -> {
      // Do things with the JSON data ...
    });
  }

我没有看到这些机制中的异步性。 在等待MonoFlux对象“做它的事情”时,这不会阻塞吗? 我不需要涉及线程或执行程序或一些类似的机制吗? 我不明白这是如何工作的,或者如何正确使用它。

我认为“订阅” MonoFlux意味着我可能会在未来某个时间收到响应(当然,它可能只是几毫秒)。 这是否意味着subscribe()调用不会阻塞?

我已经搜索并阅读了很多我发现的东西,但我仍然不清楚。 似乎缺少一条关键信息。

我想我也很难理解如何正确处理这种情况(比如上面的服务getAllProjectsForGroup()方法),我在 lambda 表达式中获取了一条信息(我认为匿名类也遇到了这个问题) 并且需要在“外部”使用它。 也许这需要作为一个单独的主题提出。

基本上像这样的反应/未来对象,包括像 CompletableFuture 这样的标准 java 对象,迫使您在从控制器到服务的整个链中使用它们。 它们是在其他线程中运行的任务。 所以你的控制器返回一个单声道,并调用你的服务返回一个单声道......你就明白了。 每个任务完成都会开始下一个。

因此,您有两个选项 afaik,要么重构 getAllProjectsForGroup 以也返回 Mono/Flux,要么使用阻塞操作(对我来说大不),例如 Mono.block(),将其转换为同步代码,但浪费线程,并且基本上使反应式代码毫无意义

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM