пустота против Моно в весеннем webflux

#java #spring #spring-boot #reactive-programming #spring-webflux

Вопрос:

Недавно я начал работать над приложением Spring Webflux с использованием реактивных потоков. У меня есть 2 вопроса.

  1. В чем разница между void и Mono<Void>
  2. У меня есть пример использования, подобный следующему, где, по моему мнению, можно было бы улучшить с помощью void или Mono<Void>
      @Service
     public class ABCService {  
       public Mono<String> getGreeting(String name) {
         Mono.just(NameValidator.validate(name))
              .map(isValid -> "Hello, " name ". Welcome!");
       }
    
     }
    
     public class NameValidator {
    
       public static boolean validate(String name) {
         if(StringUtils.isEmpty(name)) {throw new RuntimeException("Invalid name");}
         return true;
    
      }
    
     }
     

На самом деле мне не нужен метод validate (), чтобы иметь логический тип возвращаемого значения. Это могло бы быть void/Mono<Void> вместо этого. Я возвращаюсь только true к выполнению цепочки в ABCService. Может ли кто-нибудь объяснить, как сделать то же самое с помощью void и Mono<Void>

Комментарии:

1. Mono.fromRunnable(() -> NameValidator.validate(name)).thenReturn("Hello, " name ". Welcome!") — это был бы идиоматический способ выполнить это

2. Что делать, если я хочу использовать валидатор в середине реактивного конвейера? Что-то вроде этого, Mono.just(name) .map(n -> n.toUpperCase()) .map(name -> { NameValidator.validate(name); return name; }) .map(name -> "Hello, " name ". Welcome!"); Я знаю, что это надуманный пример, но у меня похожий случай использования

3. Я бы использовал его внутри doOnNext, а не на карте.

4. У меня есть 2 вопроса, 1. Когда вы хотели бы вызвать doOnNext ()? 2. Зависит ли это от того, где я его размещаю? Будет ли это действовать по-другому, если я помещу doOnNext() в качестве последнего метода() ПО сравнению с тем, если я использую между этими картами? Что делать, если я хочу, чтобы он был вызван именно в том месте, где я выполняю проверку, т. Е. после 2-й карты в приведенном выше примере.

5. Операторы выполняются в порядке объявления, поэтому имеет значение их место.

Ответ №1:

Если вы вернете Mono, вы не сможете его использовать map() . Я имею в виду, что вы можете использовать его, но так Mono<Void> как он никогда не будет выдавать значение, а только сигнал завершения, ваш map() никогда не вступит в силу. Вам нужно будет заменить его на then() :

 @Service
public class ABCService {  
  public Mono<String> getGreeting(String name) {
      NameValidator.validate(name)
         .then(Mono.just("Hello, " name ". Welcome!"));
  }
}
 

Комментарии:

1. Что делать, если я хочу использовать валидатор для уже существующей реактивной цепочки? Что-то вроде этого, Mono.just(name).map(n -> n.toUpperCase()).map(name -> { NameValidator.validate(name); return name; }).map(name -> "Hello, " name ". Welcome!");

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

3. Я новичок в webflux. Можете ли вы предложить/показать реальный способ выполнения приведенного выше примера в моем комментарии ( Mono.just(name).map(n -> n.toUpperCase())..... ) Пример немного надуман, но у меня есть похожая вещь, которую я делал в своей работе, где я получаю не name в нижней части конвейера, а скорее объект, который был получен из другого объекта над ним.

4. Что вы хотите сделать с именем, прежде чем проверять его? Преобразовать его только в верхний регистр? Является ли имя простой строкой (не Моно строки)?

5. Для простоты давайте предположим, что я только конвертирую в верхний регистр, прежде чем проверять его. Это может быть и что-то другое, а не toUpperCase() другой метод, который должен быть выполнен наверняка. Да, name это веревочка. Mono.just() даст нам Mono<String> .