【发布时间】:2021-06-09 17:28:01
【问题描述】:
我是 Reactive 编程范式的新手,但最近我决定在 Spring WebClient 上构建一个简单的 Http 客户端,因为旧的同步 RestTemplate 已经在维护中,可能会在即将发布的版本中被弃用。
所以我首先查看了 Spring 文档,然后我在网上搜索了示例。
我必须说(暂时)我有意识地决定不阅读 Reactor lib 文档,所以除了发布者-订阅者模式之外,我对 Mono 和 Flux 的了解很少.相反,我专注于让某些事情发挥作用。
我的场景是一个简单的 POST,用于向服务器发送回调,客户端只对响应状态代码感兴趣。没有返回任何身体。所以我终于想出了这个有效的代码sn-p:
private void notifyJobSuccess(final InternalJobData jobData) {
SuccessResult result = new SuccessResult();
result.setJobId(jobData.getJobId());
result.setStatus(Status.SUCCESS);
result.setInstanceId(jobData.getInstanceId());
log.info("Result to send back:" + System.lineSeparator() + "{}", result.toString());
this.webClient.post()
.uri(jobData.getCallbackUrl())
.body(Mono.just(result), ReplaySuccessResult.class)
.retrieve()
.onStatus(s -> s.equals(HttpStatus.OK), resp -> {
log.info("Expected CCDM response received with HttpStatus = {}", HttpStatus.OK);
return Mono.empty();
})
.onStatus(HttpStatus::is4xxClientError, resp -> {
log.error("CCDM response received with unexpected Client Error HttpStatus {}. "
+ "The POST request sent by EDA2 stub did not match CCDM OpenApi spec", resp.statusCode());
return Mono.empty();
})
.onStatus(HttpStatus::is5xxServerError, resp -> {
log.error("CCDM response received with unexpected Server Error HttpStatus {}", resp.statusCode());
return Mono.empty();
}).bodyToMono(Void.class).subscribe(Eda2StubHttpClient::handleResponseFromCcdm);
}
我对响应式 WebClient 工作原理的理解很差,从调用订阅开始。我在编写客户端代码之前检查的数十个示例中没有一个包含这样的调用,但事实是,在我包含该调用之前,服务器一直在等待请求。
然后我碰到了口头禅“在您订阅之前什么都不会发生”。知道 Plublisher-Subscriber 模式我知道,但我(错误地)假设订阅是由 WebClient API 在任何交换或 bodyToMono 方法中处理的...... block() 绝对必须订阅,因为当你阻止它时,请求立即发出。
所以我的第一个问题是:真的需要这个 subscribe() 调用吗?
第二个问题是为什么 StubHttpClient::handleResponse 方法永远不会被回调。为此,我发现的唯一解释是,由于返回的 Mono 是 Mono<Void>,因为响应中除了状态代码之外没有任何内容,因为它从未实例化,所以该方法完全是虚拟的......我什至可以仅用 .subscribe() 替换它。这是一个正确的假设吗?
最后,要求提供一个在 Mono 中接收主体的方法的完整示例,然后再使用它是不是太过分了?我发现的所有示例都只关注发出请求,但后来如何使用 Mono 或 Flux 现在超出了我的理解......我知道我最终必须尽快检查 Reactor 文档,但我会很感激有点帮助,因为我在处理异常和错误时遇到问题。
谢谢!
【问题讨论】:
-
I must say that I have consciously decided not to go through the Reactor lib documentation然后我建议你这样做how much research effort is expected of stack overflow users -
@ToerkTumlare,我承认在尝试使用 Spring Reactive WebClient 之前我还没有深入研究过 Reactor 文档,我很确定,就像数百人一样。但我可以肯定地说,在尝试自己寻找解决方案/解释之前,我从不发布任何问题。事实上,您正在将我重定向到一个与我的问题非常相似的问题,但没有承认尚未调查的内容。无论如何,如果你不这么认为,那对我来说很好。归根结底,我不太在乎声誉。
-
@Toerktumlare,您建议的帖子仅解决了我的第一个问题,是的,没错。有了这个,我还想发一篇文章,有人可以帮助提供一个使用 WebClient 的完整示例,而不仅仅是遍布网络的数千行代码只是为了从应用程序中获取请求,这很容易部分。
-
最后,老实说,如果您认为这个问题没有进行太多调查,我无法想象您对您所指的那个问题的看法,询问邮递员的浏览器如何处理 Mono 和Flux 调用 subscribe()... 在将其发回给我之前,您是否已阅读了两遍?拜托,如果您在这方面有经验,我认为您提供一个好的和完整的例子会更有帮助,不仅对我,而且对社区。谢谢!
标签: spring-webflux spring-webclient