"Add" 似乎在 WebFlux 中工作,但似乎必须有一个 "more accepted way"

"Add" appears to be working in WebFlux, but seems like there must be a "more accepted way"

WebFlux、反应式和处理程序的新手。

我能够从 ServerRequest 获取 Mono<> 并处理包含的 POJO 以将新元组添加到数据库。但是,似乎应该有一种 "better" 或 "more accepted" 的方式来编写这段代码。

任何使用 AccountRequestHandler 中的代码的 help/input 都将不胜感激,尤其是对建议更改背后的基本原理的解释。

路由器实现(精简到只有 "POST")...

@Configuration
public class AccountRequestRouter {

    @Bean
    public RouterFunction<ServerResponse> route(AccountRequestHandler requestHandler) {
        return nest(path("/v2"),
                   nest(accept(APPLICATION_JSON),
                      .andRoute(RequestPredicates.POST("/accounts"), requestHandler::addAccount)
                       ));
    }
}

处理程序实现... 我实际执行添加然后单独创建 ServerResponse 的代码是我所关注的。似乎 "clunky",特别是因为 AccountService.addAccount() returns 完成后是一个 Mono。

@Component
public class AccountRequestHandler {

    @Autowired
    private mil.navy.ccop.service.accounts.account.AccountService accountService;

    public Mono<ServerResponse> addAccount(ServerRequest request) {
        return request.bodyToMono(Account.class).flatMap(account -> {
                                                                        accountService.addAccount(account);
                                                                        return ServerResponse.ok().build();
                                                                    })
                                                .switchIfEmpty(ServerResponse.badRequest()
                                                                             .contentType(APPLICATION_JSON)
                                                                             .build(Mono.empty()));
    }
}

AccountService 实现(再次精简)...

@Service
class AccountService {

    @Autowired
    private AccountRepository accounts;

    public AccountService() {
    }

    public Mono<Void> addAccount(Account account) {
        Account proxy;

        // make sure that accountId is set to support auto-generation of synthetic key value
        proxy = new Account(-1, account.getShortName(), account.getLongName(), account.getDescription());
        accounts.save(proxy);
        return Mono.empty();
    }
}

感谢所有帮助提高这种编程风格的人....

首先,您有 2 个 addAccount,这可能有点令人困惑。

其次,"repository"你也在写什么?如果它是一个 sql 存储库,你需要将它正确地包装在一个 Mono.fromCallable() 中,否则它会阻塞 Reactive 线程池,你的性能可能会很差。

是的,还有其他处理方法。很多人倾向于在 flatmapmap 中做事,并且肯定在这里做事是完全可能的,但是对于 语义 我会说不太好。

mapflatmap 通常用于对单声道的内部值执行某种计算,然后 return 相同的或新的值和/或在内部输入单声道。

我会这样重写。

return 此处无效:

public void addAccount(Account account) {
    Account proxy;

    // make sure that accountId is set to support auto-generation of synthetic key value
    proxy = new Account(-1, account.getShortName(), account.getLongName(), account.getDescription());
    accounts.save(proxy);
}

这里:

public Mono<ServerResponse> addAccount(ServerRequest request) {
    return request.bodyToMono(Account.class)
                .doOnSuccess(account -> {
                            accountService.addAccount(account);
                }).then(ServerResponse.ok().build())
                  .switchIfEmpty(ServerResponse.badRequest()
                                      .contentType(APPLICATION_JSON)
                                      .build());
}

有许多不同的 doOn 方法可用于消费和处理事物 "side effects"。比如doOnSuccessdoOnErrordoOnCancel等等等等

您还有 thenthenReturn,它们只会 return 您放入其中的任何内容。 Then returns 无论你输入什么 MonothenReturn 将您放入其中的任何值都包装到 Mono 中并 returns 它。