[英]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.