Выбрать главу

@GetMapping("/recent")

public Observable<Taco> recentTacos() {

   return tacoService.getRecentTacos();

}

Аналогично, метод tacoById() может быть написан для работы с RxJava Single, а не Mono:

@GetMapping("/{id}")

public Single<Taco> tacoById(@PathVariable("id") Long id) {

   return tacoService.lookupTaco(id);

}

Кроме того, методы контроллера Spring WebFlux также могут возвращать RxJava Completable, который эквивалентен Mono<Void> в Reactor. WebFlux также может возвращать Flowable в качестве альтернативы Observable или Reactor Flux.

РЕАКТИВНАЯ ОБРАБОТКА ВХОДНЫХ ДАННЫХ

До сих пор мы интересовались только тем, какие реактивные типы возвращают методы контроллера. Но с Spring WebFlux вы также можете принять Mono или Flux в качестве входных данных для метода-обработчика. Для демонстрации рассмотрим оригинальную реализацию postTaco() из DesignTacoController:

@PostMapping(consumes="application/json")

@ResponseStatus(HttpStatus.CREATED)

public Taco postTaco(@RequestBody Taco taco) {

   return tacoRepo.save(taco);

}

postTaco() не только возвращает простой объект Taco, но также принимает объект Taco, связанный с содержимым в теле запроса. Это означает, что postTaco() не может быть вызван до тех пор, пока полезная нагрузка запроса не будет полностью подготовлена для создания экземпляра объекта Taco. Это означает, что postTaco() не может быть возвращен, пока не завершится блокирующий вызов метода save() репозитория. Другими словами, запрос блокируется дважды: при поступлении в postTaco() и снова внутри postTaco(). Но, применив небольшое реактивное кодирование к postTaco(), вы можете сделать его полностью неблокирующим методом обработки запросов:

@PostMapping(consumes="application/json")

@ResponseStatus(HttpStatus.CREATED)

public Mono<Taco> postTaco(@RequestBody Mono<Taco> tacoMono) {

   return tacoRepo.saveAll(tacoMono).next();

}

Здесь postTaco() принимает Mono<Taco> и вызывает метод saveAll() хранилища, который, как вы увидите в следующей главе, принимает любую реализацию Reactive Streams Publisher, включая Mono или Flux. Метод saveAll() возвращает Flux<Taco>, но поскольку вы работаете с Mono, вы знаете, что существует не более одного Taco, который будет опубликован Flux. Поэтому вы можете вызвать next(), чтобы получить Mono <Taco>, который вернется из postTaco().

Принимая Mono<Taco> в качестве входных данных, метод вызывается немедленно, не дожидаясь готовности Taco на основе тела запроса. И поскольку репозиторий также является реактивным, он примет Mono и немедленно вернет Flux<Taco>, из которого вы вызываете next(), и вернете полученный Mono<Taco> ... и все это еще до того, как запрос будет обработан!

Spring WebFlux является фантастической альтернативой Spring MVC, предлагая возможность написания реактивных веб-приложений с использованием той же модели разработки, что и Spring MVC. Но у Spring 5 есть еще одна новая хитрость. Давайте посмотрим, как создавать реагирующие API, используя новый функциональный стиль программирования Spring 5.

11.2 Определение функциональных обработчиков запросов

Модель программирования Spring MVC, основанная на аннотациях, существует начиная с Spring 2.5 и пользуется большой популярностью. Это имеет несколько недостатков.

Во-первых, любое программирование на основе аннотаций включает разделение в определении того, что аннотация должна делать и как она должна это делать. Сами аннотации определяют, что; а как это определено в другом месте в рамках кода. Это усложняет модель программирования, когда речь заходит о какой-либо настройке или расширении, поскольку такие изменения требуют работы в коде, внешнем по отношению к аннотации. Более того, отладка такого кода сложна, потому что вы не можете установить точку останова для аннотации.

Кроме того, поскольку популярность Spring продолжает расти, разработчики, впервые познакомившиеся с Spring в других языках и фреймворках, могут обнаружить что Spring MVC (и WebFlux) на основе аннотаций совсем не такой, как они уже его знают. В качестве альтернативы WebFlux Spring 5 представил новую модель функционального программирования для определения реактивных API.

Эта новая модель программирования используется больше как библиотека и меньше как фреймворк, позволяя сопоставлять запросы с кодом обработчика без аннотаций. Написание API с использованием модели функционального программирования Spring включает четыре основных типа:

-RequestPredicate — объявляет виды запросов, которые будут обработаны.

-RouterFunction - бъявляет, как соответствующий запрос должен быть направлен в код обработчика.

-ServerRequest - представляет собой HTTP-запрос, включая доступ к информации в header и body.

-ServerResponse - представляет ответ HTTP, включая информацию header и body