簡體   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