«Добавить», кажется, работает в WebFlux, но, похоже, должен быть «более приемлемый способ» - PullRequest
0 голосов
/ 03 июля 2019

Новое в WebFlux, реактиве и обработчиках.

Я могу получить Mono <> из ServerRequest и обработать содержащийся 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 голосов
/ 04 июля 2019

ну, во-первых, у вас есть 2 addAccount, что может немного сбить с толку.

Во-вторых, о каком «хранилище» вы пишете?если это репозиторий sql, вам нужно правильно обернуть его в Mono.fromCallable(), иначе он заблокирует пул потоков Reactive и у вас может быть действительно плохая производительность.

Да, есть другие способы сделать что-то.Многие люди склонны делать что-то в flatmap или map и уверены, что здесь вполне можно сделать что-то, но для семантики я бы сказал, что это менее хорошо.

map и flatmap обычно используются для выполнения каких-либо вычислений внутреннего значения моно, а затем возвращают то же или новое значение и / или тип внутри моно.

я бы переписалвот так вот.

здесь возвращено значение void:

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 методов, которые должны бытьпривыкли потреблять и делать «побочные эффекты» на вещи.Как doOnSuccess, doOnError, doOnCancel и т. Д. И т. Д.

у вас также есть then и thenReturn, которые просто вернут все, что вы в них положили.Then возвращает то, что Mono вы положили в него.thenReturn упаковывает любое значение, которое вы положили в него, в Mono и возвращает его.

...