【问题标题】:"Add" appears to be working in WebFlux, but seems like there must be a "more accepted way"“添加”似乎在 WebFlux 中工作,但似乎必须有一个“更可接受的方式”
【发布时间】:2019-11-14 14:05:41
【问题描述】:

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

我能够从 ServerRequest 获取 Mono 并处理包含的 POJO 以将新元组添加到数据库。但是,似乎应该有一种“更好”或“更容易接受”的方式来编写这段代码。

如果对 AccountRequestHandler 中的代码提供任何帮助/输入,我们将不胜感激,尤其是对建议更改背后的基本原理的解释。

路由器实现(精简为仅“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 的代码是我关注的内容。这似乎很“笨拙”,特别是因为 AccountService.addAccount() 在完成时返回一个 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();
    }
}

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

【问题讨论】:

    标签: functional-programming httpresponse spring-webflux


    【解决方案1】:

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

    其次,您也在编写什么样的“存储库”?如果它是一个 sql 存储库,则需要将其正确包装在 Mono.fromCallable() 中,否则它将阻塞 Reactive 线程池,并且性能会非常差。

    是的,还有其他的做事方式。很多人倾向于在flatmapmap 中做事,当然这里完全可以做事,但是对于语义,我会说它不太好。

    mapflatmap 通常用于对单声道的内部值执行某种计算,然后返回相同的或新的值或单声道内的类型​​。

    我会这样重写。

    在这里返回无效:

    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 方法可用于消费和对事物产生“副作用”。比如doOnSuccessdoOnErrordoOnCancel等等等等。

    您还拥有thenthenReturn,它们只会返回您放入其中的任何内容。 Then 返回您放入的任何 MonothenReturn 将您放入其中的任何值包装到 Mono 中并返回它。

    【讨论】:

    • 谢谢!我想我只需要坐下来认真阅读 Mono 和 Flux 的 Javadocs。
    • 我正在写一个 SQL (PostgreSQL) 存储库。我一直在监视 PostgreSQL 的 R2DBC 工作,并会在它进入 GA 时采用它。但是,我会研究您对 Mono.fromCallable 的建议。
    • 很好奇为什么您建议将 public Mono addAccount(Account) 更改为 public void addAccount(Account)。质疑是因为我的意图是,当它发布时,采用 PostgreSQL 的 R2DBC 实现,我相信这将返回单声道和通量。
    • 没有什么特别的原因,因为它是一个“阻塞”调用,更容易将其作为“非反应性”方法处理,并将非反应性代码与反应性代码分开。我刚刚选择了简单的 doOnSucess 方法,它返回 void,因此其中的任何方法都需要返回 void。如果您将通话包装在 Mono.fromCallable 我认为您需要返回像 Mono 这样的单声道
    • 我喜欢代码是不言自明的,当我编写示例首先获取,然后我们执行OnSuccess,然后我们返回时,这对我来说很明显。但它更像是一种代码风格,而不是“这是对的,这是错误的”
    猜你喜欢
    • 2020-07-25
    • 2020-01-31
    • 2013-11-25
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多