关于Java 8:在Mono <Object>的单个管道中多次使用Flatmap是否更好?

Is it preferable using flatmap multiple times in a single pipe of Mono<Object>

作为开发团队的一部分,我们想要构建一个非阻塞应用程序,因为我们正在使用Spring Reactor 3构建应用程序。因此,在使用项目Reactor时,我有一个列表问题:

  • 在单个管道和Mono<object>上使用多个flatMap是一个好习惯,例如,如果emp的所有详细信息都有效,则存在验证emp信息的场景:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    @Getter
    @Setter
    public class Employee {
         private long empId;
         private String userName;
         private String password;

    }
    public class FlatMapExample{
    public Mono<Emplyoee> doValidate(Emplyoee emp){

        Mono.just(emp).flatMap(this::validateEmpId)
              .flatMap(this::validateUserName)
              .flatMap(this::validatePassword);
    }
    private Mono<Emplyoee> validateEmpId(Emplyoee e){
     Mono.just(emp).flatMap(//here some check on empId)
    }

    private Mono<Emplyoee> validateUserName(Emplyoee e){
     Mono.just(emp).flatMap(//here some check userName calling another method which is performing some extra checks like the format of username/ null or empty userName)
    }

    private Mono<Emplyoee> validatePassword(Emplyoee e){
     Mono.just(emp).flatMap(//here some check to validate password by calling another method)
    }

    }
  • 与地图相比,flatMap在资源方面的成本更高吗?

  • 如果将使用映射,则映射内部调用的方法应返回一个简单的对象,例如,在上述情况下,如果使用映射,则validateEmpId和其他方法的返回类型将仅为Employee。因此,在这些方法中,我们不能使用管道,而是简单的Java或我们可以使用Java流。因此,在我看来,这将不是功能编程。

  • 我认为您应该尝试简化您的验证api,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public Mono<Void> doValidate(Emplyoee emp){
      return validateEmpId(emp.getId())
        .then(validateUserName(emp.getUserName()))
        .then(validatePassword(emp);
    }
    private Mono<Void> validateEmpId(long id){
      // here some check on empId

      // if check ok return Mono.empty()
      // else return Mono.error(new YourException(...))
    }
    private Mono<Void> validateUserName(String userName){
      ...
    }
    private Mono<Void> validatePassword(Emplyoee emp){
      ...
    }

    没有更多的Mono.just(emp).flatMap


    数据验证是关键点,所以我认为最好是同步此过程。

    此外,如果flatMap(this :: validateEmpId)返回Mono.error(smth),则您的下一个验证器将不会执行,因此您将无法返回完整的错误消息。

    本文的作者在webflux(反应器)项目中使用Validator,因此我相信在您的示例中,更好的方法是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    public Mono<Emplyoee> doValidate(Emplyoee emp){
        /*validate */
        if(valid) {
            return Mono.just(emp);
        } else {
            return Mono.error(err);
        }
    }