最近,我的一位同事向我介绍了Project Reactor类型的expand运算符,在这篇文章中,我想介绍几种使用它的方式。
展开分页结果
考虑在名为City的模型上基于Spring Data的存储库:
import org.springframework.data.jpa.repository.JpaRepository; import samples.geo.domain.City; public interface CityRepo extends JpaRepository<City, Long> { }
该存储库提供了一种检索分页结果的方法,大致如下:
cityRepo.findAll(PageRequest.of( 0 , 5 ))
现在,如果我要将多个页面展开到一个结果中,执行此操作的方法将是以下一种循环:
var pageable: Pageable = PageRequest.of( 0 , 5 ) do { var page: Page<City> = cityRepo.findAll(pageable) page.content.forEach { city -> LOGGER.info( "City $city" ) } pageable = page.nextPageable() } while (page.hasNext())
可以使用Reactor expand运算符通过以下方式完成分页结果的等效展开:
val result: Flux<City> = Mono .fromSupplier { cityRepo.findAll(PageRequest.of( 0 , 5 )) } .expand { page -> if (page.hasNext()) Mono.fromSupplier { cityRepo.findAll(page.nextPageable()) } else Mono.empty() } .flatMap { page -> Flux.fromIterable(page.content) } result.subscribe( { page -> LOGGER.info( "City ${page}" ) }, { t -> t.printStackTrace() } )
在这里,结果的第一页扩展到第二页,第二页扩展到第三页,依此类推,直到没有要检索的页面为止。
遍历一棵树
考虑以下模型表示的树结构中的节点:
data class Node( val id: String, val nodeRefs: List<String>, )
样本数据如下所示:
可以使用如下所示的调用遍历:
val rootMono: Mono<Node> = nodeService.getNode( "1" ) val expanded: Flux<Node> = rootMono.expand { node -> Flux.fromIterable(node.childRefs) .flatMap { nodeRef -> nodeService.getNode(nodeRef) } } expanded.subscribe { node -> println(node) }
这是广度优先的扩展,输出如下所示:
Node- 1 Node- 1 - 1 Node- 1 - 2 Node- 1 - 1 - 1 Node- 1 - 1 - 2 Node- 1 - 2 - 1 Node- 1 - 2 - 2
expandDeep变体将深度优先遍历
翻译自: https://www.javacodegeeks.com/2020/02/project-reactor-expand-method.html