“添加”似乎在WebFlux中工作,但似乎必须有一种“更被接受的方式”

时间:2019-07-03 20:39:46

标签: functional-programming httpresponse spring-webflux

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();
    }
}

感谢所有帮助,以增强这种编程风格。...

1 个答案:

答案 0 :(得分:0)

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

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

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

mapflatmap通常用于对Mono的内部值执行某种计算,然后返回相同或新的值或在Mono内部键入。

我会这样重写。

在此处返回空白:

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中并返回它。