Spring WebFlux - как получить данные из запроса? - PullRequest
0 голосов
/ 06 февраля 2019

Пытаясь перенести мое приложение Spring Boot на WebFlux, я начал преобразовывать файл, оставляя хранилище нетронутым (т. Е. Доступ к БД - это синхронизация и блокировка).У меня возникают проблемы с получением данных из типов Mono / Flux и их пересылкой в ​​хранилище.

Рассмотрим следующее

@POST
@Path("/register")
public String register( String body ) throws Exception
{
    ObjectMapper objectMapper = json();

    User user = objectMapper.readValue( body, User.class );

    int random = getRandomNumber( 111111, 999999 );

    String uuid = null;

    //first, check if user already did registration from that phone
    UserDbRecord userDbRecord = UserDAO.getInstance().getUserByPhone( user.phone );

    if( userDbRecord != null )
    {
        logger.info( "register. User already exist with phone: " + user.phone + ", id: " + userDbRecord.getId() );

        uuid = userDbRecord.getToken();
    }
    else
    {
        uuid = UUID.randomUUID().toString();
    }

    SMS.send( user.phone, random );

    Auth auth = new Auth();
    auth.token = uuid;

    return objectMapper.writeValueAsString( auth );
}

Итак, пытаемся сделать следующее:

public Mono<ServerResponse> register( ServerRequest request )
{
    Mono<User> user = request.bodyToMono( User.class );

    Mono<UserDbRecord> userDbRecord = user.flatMap( u -> Mono.just( userRepository.findByPhone( u.phone ) ) );

    int random = getRandomNumber( 111111, 999999 );

    String uuid = null;

    //first, check if user already did registration from that phone

    //now what???
    if( userDbRecord != null )
    {
        logger.info( "register. User already exist with phone: " + userDbRecord.getPhone() + ", id: " + userDbRecord.getId() );

        uuid = userDbRecord.getToken();
    }
    else
    {
        uuid = UUID.randomUUID().toString();
    }

    SMS.send( user.phone, random );

    Auth auth = new Auth();
    auth.token = uuid;

    return ok().contentType( APPLICATION_JSON ).syncBody( auth );
}

Каков наилучший способ проверить, является ли userDbRecord Mono пустым, а если нет, извлечь свойство телефона из него?

1 Ответ

0 голосов
/ 07 февраля 2019

Переосмыслите способ обработки данных

В Реактивном программировании с использованием RxJava или Project Reactor действительно важно продолжить ваш поток от начала до конца.

В вашем случае вынеобходимо заменить обязательные проверки / проверки на реактивные:

public Mono<ServerResponse> register( ServerRequest request )
{
    return request
        .bodyToMono( User.class )
        // make sure you use Reactive DataBase Access in order to 
        // get the all benefits of Non-Blocking I/O with Project Reactor
        // if you use JPA - consider Moving to R2DBC r2dbc.io
        .flatMap( user -> // <1>
            Mono.just( userRepository.findByPhone( user.phone ) ) // <2>
                .map(userDbRecord -> {
                    logger.info( "register. User already exist with phone: " + userDbRecord.getPhone() + ", id: " + userDbRecord.getId() );
                    return userDbRecord.getToken();
                })
                .switchIfEmpty(Mono.fromSupplier(() -> UUID.randomUUID().toString())) <3>
                .flatMap(uuid -> {
                    SMS.send( user.phone, random ); <4>
                    Auth auth = new Auth();
                    auth.token = uuid;
                    return ok().contentType( APPLICATION_JSON ).syncBody( auth );
                })
        );
}

В приведенном выше примере показано, как можно переписать метод императивного контроллера на реактивный.Я поместил пару комментариев и описаний к ним ниже:

  1. Здесь я использую flatMap, чтобы сохранить доступ к User Сущности в создаваемом закрытии.
  2. Убедитесь, чтовы используете неблокирующий реактивный ввод / вывод из конца в конец -> игнорирование этого правила может привести к сведению на нет всех преимуществ WebFlux.Если вы используете JPA, рассмотрите возможность перехода на R2DBC и Spring Data R2DBC, которые обеспечивают реактивную неблокирующую замену для JPA
  3. . Частое генерирование UUID может привести к блокировке потока -> https://stackoverflow.com/a/14533384/4891253
  4. Убедитесь, что это не блокирует
...