Класс Mono в Java: что такое и когда использовать?

У меня есть следующий код:

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Component
public class GreetingHandler 
    public Mono<ServerResponse> hello(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
        .body(BodyInserters.fromValue("Hello Spring!"));
    }
}

Я понимаю этот код, за исключением того, что делает класс Mono и каковы его особенности. Я много искал, но не сразу переходил к делу: что такое класс Mono и когда его использовать?

1 ответ

А Mono<T> специализированный Publisher<T> который излучает не более одного элемента, а затем (необязательно) завершается onComplete сигнал или onErrorсигнал. Он предлагает только подмножество операторов, доступных дляFlux, и некоторые операторы (особенно те, которые объединяют Mono с другим Publisher) переключиться на Flux. Например,Mono#concatWith(Publisher) возвращает Flux пока Mono#then(Mono) возвращает другой Mono. Обратите внимание, что вы можете использоватьMonoдля представления асинхронных процессов без значения, которые имеют только концепцию завершения (аналогично Runnable). Чтобы создать его, вы можете использовать пустойMono<Void>.

Mono и Flux являются реактивными потоками. Они различаются тем, что выражают. Mono - это поток от 0 до 1 элемента, а Flux - это поток от 0 до N элементов.

Это различие в семантике этих двух потоков очень полезно, поскольку, например, при запросе к серверу Http ожидается получение 0 или 1 ответа, в этом случае было бы неуместно использовать Flux. Напротив, вычисление результата математической функции на интервале предполагает получение одного результата на число в интервале. В этом другом случае уместно использовать Flux.

Как это использовать:

Mono.just("Hello World !").subscribe(
  successValue -> System.out.println(successValue),
  error -> System.error.println(error.getMessage()),
  () -> System.out.println("Mono consumed.")
);
// This will display in the console :
// Hello World !
// Mono consumed.

// In case of error, it would have displayed : 
// **the error message**
// Mono consumed.

Flux.range(1, 5).subscribe(
  successValue -> System.out.println(successValue),
  error -> System.error.println(error.getMessage()),
  () -> System.out.println("Flux consumed.")
);
// This will display in the console :
// 1
// 2
// 3
// 4
// 5
// Flux consumed.

// Now imagine that when manipulating the values in the Flux, an exception
// is thrown for the value 4. 
// The result in the console would be :
// An error as occured
// 1
// 2
// 3
//
// As you can notice, the "Flux consumed." doesn't display because the Flux
// hasn't been fully consumed. This is because the stream stop handling future values
// if an error occurs. Also, the error is handled before the successful values.

источники: Reactor Java #1 - Как создать Mono и Flux?, Моно, асинхронный результат 0-1

это может быть полезно: Mono doc

Другие вопросы по тегам