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

-Операции создания

-Комбинированные операции

-Операции трансформации

-Логические операции

Как бы ни было интересно смотреть на каждую из 500 операций, чтобы увидеть, как они работают, в этой главе просто не хватит места. В этом разделе я выбрал несколько наиболее полезных операций для экспериментов. Начнем с операций создания.

ПРИМЕЧАНИЕ

Где примеры Mono? Mono и Flux используют много одинаковых операций, поэтому в большинстве случаев нет необходимости показывать одну и ту же операцию дважды, один раз для Mono и еще раз для Flux. Более того, хотя операции Mono полезны, на них немного менее интересно смотреть, чем на те же самые операции, когда предоставляется Flux. Большинство примеров, с которыми мы будем работать, будут связаны с Flux. Просто знайте, что Mono обычно имеет эквивалентные операции.

10.3.1 Реактивные типы создания

Часто при работе с реактивными типами в Spring вы получаете Flux или Mono из репозитория или службы, поэтому вам не нужно создавать их самостоятельно. Но иногда вам нужно будет создать нового реактивного издателя.

Reactor предоставляет несколько операций для создания Flux и Mono. В этом разделе мы рассмотрим некоторые из наиболее полезных операций создания.

СОЗДАНИЕ ИЗ ОБЪЕКТОВ

Если у вас есть один или несколько объектов, из которых вы хотите создать Flux или Mono, вы можете использовать статический метод just() в Flux или Mono для создания реактивного типа, данные которого управляются этими объектами. Например, следующий метод тестирования создает Flux из пяти объектов String:

@Test

public void createAFlux_just() {

   Flux<String> fruitFlux = Flux

      .just("Apple", "Orange", "Grape", "Banana", "Strawberry");

}

На данный момент Flux создан, но у него нет подписчиков. Без подписчиков данные не будут передаваться. Думая об аналогии с садовым шлангом, вы прикрепили садовый шланг к патрубку, и с другой стороны есть вода из коммунальной компании - но пока вы не включите патрубок, вода не будет течь. Подписка на реактивный тип - это то, как вы включаете поток данных.

Чтобы добавить подписчика, вы можете вызвать метод subscribe() в Flux:

fruitFlux.subscribe(

   f -> System.out.println("Here's some fruit: " + f)

);

Здесь лямбда, заданная для subscribe(), на самом деле является java.util.Consumer, который используется для создания Reactive Streams Subscriber. При вызове subscribe() данные начинают передаваться. В этом примере промежуточных операций нет, поэтому данные передаются напрямую от Flux к Subscriber.

Печать записей из Flux или Mono на консоль - это хороший способ увидеть реактивный тип в действии. Но лучший способ на самом деле протестировать Flux или Mono - использовать StepVerifier от Reactor. С учетом Flux или Mono, StepVerifier подписывается на реактивный тип и затем применяет утверждения к данным, когда они проходят через поток, в конце концов проверяя, что поток завершается должным образом.

Например, чтобы проверить, что предписанные данные проходят через fruitFlux, вы можете написать тест, который выглядит следующим образом:

StepVerifier.create(fruitFlux)

   .expectNext("Apple")

   .expectNext("Orange")

   .expectNext("Grape")

   .expectNext("Banana")

   .expectNext("Strawberry")

   .verifyComplete();

В этом случае StepVerifier подписывается на Flux и затем утверждает, что каждый элемент соответствует ожидаемому названию плода. Наконец, он проверяет, что после того, как клубника произведена Flux, Flux завершается.

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

СОЗДАНИЕ ИЗ КОЛЛЕКЦИЙ

Flux также может быть создан из массива, Iterable или Java Stream. Рисунок 10.3 иллюстрирует, как это работает с мраморной диаграммой.

Рисунок 10.3. Поток может быть создан из массива, Iterable или Stream.

Чтобы создать Flux из массива, вызовите статический метод fromArray(), передав в исходный массив:

@Test

public void createAFlux_fromArray() {

   String[] fruits = new String[] {

      "Apple", "Orange", "Grape", "Banana", "Strawberry" };

   Flux<String> fruitFlux = Flux.fromArray(fruits);

   StepVerifier.create(fruitFlux)

      .expectNext("Apple")

      .expectNext("Orange")

      .expectNext("Grape")

      .expectNext("Banana")

      .expectNext("Strawberry")

      .verifyComplete();

}

Поскольку исходный массив содержит те же имена фруктов, которые вы использовали при создании Flux из списка объектов, данные, передаваемые Flux, будут иметь те же значения. Таким образом, вы можете использовать тот же StepVerifier, что и раньше, чтобы проверить этот Flux.

Если вам нужно создать Flux из java.util.List, java.util.Set или любой другой реализации java.lang.Iterable, вы можете передать его в статический метод fromIterable():