[英]Need help understanding reactive Mono/Flux classes
我正在編寫一個 Java 應用程序並嘗試使用 Spring WebFlux WebClient
來調用 REST API。 我剛開始使用這個庫,幾乎沒有“反應式”編程的經驗。 我很難理解Mono
和Flux
類是如何工作和使用的。 在這一點上我了解的很少,這些類允許對某種數據源(例如遠程 Web 服務)進行異步操作。 WebFlux 中的一切似乎都處理Mono
或Flux
對象。
在這一點上,我最大的問題/困惑是,如果它們允許異步處理,我們如何在異步進程和啟動它的進程之間架起橋梁? 我最近(大約 10 年前)對此類處理的經驗涉及Executor
和Future
。 我也花了一些時間來掌握這些。 (我也忘記了很多。)
這是我編寫的一些代碼,試圖幫助說明我的意思。
@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 ...
});
}
我沒有看到這些機制中的異步性。 在等待Mono
或Flux
對象“做它的事情”時,這不會阻塞嗎? 我不需要涉及線程或執行程序或一些類似的機制嗎? 我不明白這是如何工作的,或者如何正確使用它。
我認為“訂閱” Mono
或Flux
意味着我可能會在未來某個時間收到響應(當然,它可能只是幾毫秒)。 這是否意味着subscribe()
調用不會阻塞?
我已經搜索並閱讀了很多我發現的東西,但我仍然不清楚。 似乎缺少一條關鍵信息。
我想我也很難理解如何正確處理這種情況(比如上面的服務getAllProjectsForGroup()
方法),我在 lambda 表達式中獲取了一條信息(我認為匿名類也遇到了這個問題) 並且需要在“外部”使用它。 也許這需要作為一個單獨的主題提出。
基本上像這樣的反應/未來對象,包括像 CompletableFuture 這樣的標准 java 對象,迫使您在從控制器到服務的整個鏈中使用它們。 它們是在其他線程中運行的任務。 所以你的控制器返回一個單聲道,並調用你的服務返回一個單聲道......你就明白了。 每個任務完成都會開始下一個。
因此,您有兩個選項 afaik,要么重構 getAllProjectsForGroup 以也返回 Mono/Flux,要么使用阻塞操作(對我來說大不),例如 Mono.block(),將其轉換為同步代碼,但浪費線程,並且基本上使反應式代碼毫無意義
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.