WebFlux 功能:如何检测空 Flux 并返回 404?

Posted

技术标签:

【中文标题】WebFlux 功能:如何检测空 Flux 并返回 404?【英文标题】:WebFlux functional: How to detect an empty Flux and return 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)

【问题讨论】:

【参考方案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 的最佳方式吗?

以上是关于WebFlux 功能:如何检测空 Flux 并返回 404?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Webflux 中返回 Mono<Map<String, Flux<Integer>>> 响应?

Spring 5 WebFlux Mono 和 Flux

Spring WebFlux,单元测试 Mono 和 Flux

Spring WebFlux(Flux):如何动态发布

从 Spring WebFlux 返回 Flux<String> 返回一个字符串而不是 JSON 中的字符串数组

Log Spring webflux 类型 - Mono 和 Flux