【问题标题】:WebFlux functional: How to detect an empty Flux and return 404?WebFlux 功能:如何检测空 Flux 并返回 404?
【发布时间】:2018-02-04 19:50:54
【问题描述】:

我有以下简化的处理函数(Spring WebFlux 和使用 Kotlin 的函数式 API)。但是,我需要提示如何检测空的 Flux,然后在 Flux 为空时使用 noContent() 处理 404。

fun findByLastname(request: ServerRequest): Mono<ServerResponse> {
    val lastnameOpt = request.queryParam("lastname")
    val customerFlux = if (lastnameOpt.isPresent) {
        service.findByLastname(lastnameOpt.get())
    } else {
        service.findAll()
    }
    // How can I detect an empty Flux and then invoke noContent() ?
    return ok().body(customerFlux, Customer::class.java)
}

【问题讨论】:

    标签: spring spring-boot kotlin spring-webflux project-reactor


    【解决方案1】:

    使用Flux.hasElements() : Mono&lt;Boolean&gt;函数:

    return customerFlux.hasElements()
                       .flatMap {
                         if (it) ok().body(customerFlux)
                         else noContent().build()
                       }
    

    【讨论】:

      【解决方案2】:

      我不确定为什么没有人谈论使用 Flux.java 的 hasElements() 函数,它会返回一个 Mono。

      【讨论】:

        【解决方案3】:

        除了Brian的解决方案,如果你不想一直对列表做空检查,你可以创建一个扩展函数:

        fun <R> Flux<R>.collectListOrEmpty(): Mono<List<R>> = this.collectList().flatMap {
                val result = if (it.isEmpty()) {
                    Mono.empty()
                } else {
                    Mono.just(it)
                }
                result
            }
        

        并像在 Mono 中那样调用它:

        return customerFlux().collectListOrEmpty()
                             .switchIfEmpty(notFound().build())
                             .flatMap(c -> ok().body(BodyInserters.fromObject(c)))
        

        【讨论】:

          【解决方案4】:

          来自Mono

          return customerMono
                     .flatMap(c -> ok().body(BodyInserters.fromObject(c)))
                     .switchIfEmpty(notFound().build());
          

          来自Flux

          return customerFlux
                     .collectList()
                     .flatMap(l -> {
                         if(l.isEmpty()) {
                           return notFound().build();
          
                         }
                         else {
                           return ok().body(BodyInserters.fromObject(l)));
                         }
                     });
          

          请注意,collectList 在内存中缓冲数据,因此这可能不是大型列表的最佳选择。可能有更好的方法来解决这个问题。

          【讨论】:

          • 修改后的变体也不起作用。当原始 Flux 为空时,customerFlux.collectList() 导致 Mono 包含一个空列表。因此,Mono 不为空(因为它包含一个空列表)并调用了 ok()。
          • 找到解决方案。在flatMap() 内部需要一个if 语句:if (l.isEmpty()) notFound()... else ok()... 然后switchIfEmpty(...) 在此处已过时。
          • 这仍然是在空 Flux 上返回 404 的最佳方式吗?
          猜你喜欢
          • 1970-01-01
          • 2019-04-25
          • 1970-01-01
          • 2018-01-26
          • 2020-03-20
          • 2021-05-16
          • 2021-09-28
          • 2021-07-30
          • 2018-12-19
          相关资源
          最近更新 更多