我有一個使用 Spring WebFlux 框架構建的 REST API,我有一個端點,它回傳一個Flux<ChannelResponse>,其中ChannelResponse是一個樹結構的物件,如下所示:
public record ChannelResponse(
long id,
List<ChannelResponse> children
) {}
現在,我對反應式編程范式沒有太多經驗,但這就是我將如何使用同步邏輯實作這樣一個端點,這樣每個頂級通道(那些沒有父級的通道)都被轉換為一個ChannelResponse物件樹:
public Flux<ChannelResponse> getAll() {
return channelRepository.findAllByParentChannelIdOrderByOrdinality(null)
.map(channel -> getChannelDataRecursive(channel));
}
private FullChannelResponse getChannelDataRecursive(Channel channel) {
var children = channelRepository.findAllByParentChannelIdOrderByOrdinality(channel.getId())
.collectList().block();
List<ChannelResponse> childData = new ArrayList<>();
for (var child : children) {
childData.add(getChannelDataRecursive(child));
}
return new ChannelResponse(channel.getId(), childData);
}
顯然這在 WebFlux 中不起作用,因為我正在嘗試執行阻塞存盤庫呼叫。
有沒有辦法以異步方式生成這種遞回資料結構?或者如果沒有,我有哪些混合同步和異步代碼來實作這個結果的選擇?
uj5u.com熱心網友回復:
我能夠以一種有點奇怪的方式解決它,即使用expandDeep運算子生成所有頻道的平面串列,排序后每個父級都緊跟其子級集。然后我使用一個簡單的同步遞回方法將這些資料轉換為所需的格式:
public Flux<ChannelResponse> getAll() {
return channelRepository.findAllByParentChannelIdOrderByOrdinality(null)
.expandDeep(channel -> channelRepository.findAllByParentChannelIdOrderByOrdinality(channel.getId()))
.collectList()
.flatMapMany(channels -> Flux.fromIterable(buildRecursiveChannelResponse(null, channels)));
}
public List<ChannelResponse> buildRecursiveChannelResponse(Long parent, List<Channel> channels) {
List<ChannelResponse> responses = new ArrayList<>();
while (!channels.isEmpty()) {
Channel c = channels.get(0);
if (!Objects.equals(c.getParentChannelId(), parent)) return responses;
channels.remove(0);
var children = buildRecursiveChannelResponse(c.getId(), channels);
responses.add(new ChannelResponse(c.getId(), children));
}
return responses;
}
我覺得這個解決方案不是最優的,因為它需要對頻道串列的排序方式有非常具體的了解,以便生成樹結構。請讓我知道是否有更清潔的方法來做到這一點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/334914.html
標籤:爪哇 递归 反应式编程 弹簧-webflux 项目反应堆
上一篇:從動態嵌套陣列生成物件的平面陣列
