gpt4 book ai didi

java - spring webflux如何在响应式(Reactive)世界中管理顺序业务逻辑代码

转载 作者:行者123 更新时间:2023-12-02 10:46:44 27 4
gpt4 key购买 nike

这种方法是否响应式友好?

我有一个响应式(Reactive) Controller “保存”方法,调用 myService.save(request)。

服务层需要:

  1. jdbc 保存(在另一个调度程序上,因为代码阻塞),
  2. 生成模板字符串(在另一个调度程序上),
  3. 发送电子邮件(在另一个调度程序上),
  4. 最终将保存的实体返回给 Controller 层

我无法将所有调用链接到一个管道中,或者我不知道如何实现这一点,因为我想在执行 ....flatMap(templateService: 后立即发送回丢失的 (1) :generateStringTemplate) 例如。

因此,我在 (1) 内触发子操作。

我应该如何处理这个问题,还是有一种聪明的方法可以在一个管道中做到这一点?

下面的代码来支持这个问题。谢谢。

Controller层调用的服务

    public Mono<Prospect> save(final Prospect prospect) {

return Mono.fromCallable(
() -> {
Prospect savedProspect = transactionTemplate.execute(status -> prospectRepository.save(prospect));

templateService.generateProspectSubscription(savedProspect)
.map(t ->
EmailPostRequest.builder()
...
.build())
.flatMap(emailService::send)
.subscribe();

return savedProspect;
})
.subscribeOn(jdbcScheduler);

}

模板服务

public Mono<String> generateProspectSubscription(final Prospect prospect) {        
return Mono.fromCallable(
() -> {
Map<String, Object> model = new HashMap<>();
...

Template t = freemarkerConfig.getTemplate(WELCOME_EN_FTL);
String html = FreeMarkerTemplateUtils.processTemplateIntoString(t, model);
return html;
}
).subscribeOn(freemarkerScheduler);
}

电子邮件服务

 public Mono<Void> send(final EmailPostRequest e) {

return Mono.fromCallable(
() -> {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper mimeHelper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());


mimeHelper.setTo(e.getTo());
mimeHelper.setText(e.getText(), true);
mimeHelper.setSubject(e.getSubject());
mimeHelper.setFrom(new InternetAddress(e.getFrom(), e.getPersonal()));

emailSender.send(message);

return Mono.empty();
}
).subscribeOn(emailScheduler).then();
}

编辑服务我认为这个版本的服务层更干净,但欢迎任何评论

    public Mono<Prospect> save(final Prospect prospect) {

return Mono.fromCallable(
() -> transactionTemplate.execute(status -> prospectRepository.save(prospect)))
.subscribeOn(jdbcScheduler)
.flatMap(savedProspect -> {
templateService.generateProspectSubscription(savedProspect)
.map(t ->
EmailPostRequest.builder()
...
.build())
.flatMap(emailService::send)
.subscribe();

return Mono.just(savedProspect);
}
);
}

最佳答案

这种方法不是响应式友好的,因为您 100% 包装了阻塞库。通过此用例,您无法真正看到响应式运行时的好处,并且应用程序的性能很可能比阻塞式应用程序更差。

如果您的主要动机是绩效,那么这可能会适得其反。将大量阻塞 I/O 工作卸载到专门的调度程序会产生内存(创建更多线程)和 CPU(上下文切换)方面的运行时成本。如果性能和可扩展性是您最关心的问题,那么切换到 Spring MVC 并在合适的地方利用 Flux/Mono 支持,甚至调用 block() 运算符可能更合适。

如果您的主要动机是使用特定的库,例如 Spring Framework 的 WebClient 与 Spring MVC,那么您最好在选定的位置使用 .block() 运算符而不是包装和安排一切。

关于java - spring webflux如何在响应式(Reactive)世界中管理顺序业务逻辑代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52499782/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com