You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring 5 WebFlux中RouterFunction如何返回正确的Destination列表?

问题:WebFlux RouterFunction返回的目的地列表无法正确序列化

嘿,我帮你看看这个问题~你现在遇到的情况是,用ResponseData包装反应式流Flux<Destination>时,返回的不是实际的目的地数据列表,而是Flux对象的内部属性。先梳理下你的现有代码和错误返回结果:

你的RouterFunction Bean

@Bean
RouterFunction<?> routes(DestinationHandler destinationHandler) {
    return nest(path("/destination"), route(method(GET), destinationHandler::findAll));
}

处理器函数及相关方法

public Mono<ServerResponse> findAll(ServerRequest request) {
    Flux<Destination> destinations = destinationService.findAll();
    ResponseData responseData = buildResponseData(destinations);
    return ok().body(Mono.just(responseData), ResponseData.class);
}

private ResponseData buildResponseData(Flux<Destination> destinations) {
    ResponseData responseData = new ResponseData();
    responseData.setStatus(HttpStatus.OK.value());
    responseData.setCode(DESTINATION_LIST_SUCCESS_CODE);
    responseData.setMessage(DESTINATION_LIST_SUCCESS_MESSAGE);
    responseData.setData(destinations);
    return responseData;
}

错误返回结果

{
    "status":200,
    "code":"destination_list_success",
    "message":"Retorno realizado com sucesso",
    "data":{
        "scanAvailable":true,
        "prefetch":-1
    }
}

问题原因

这是因为你直接把Flux<Destination>这个反应式流对象赋值给了ResponseData的data字段。序列化框架(比如Jackson)处理它时,只会输出Flux自身的内部属性,并不会去订阅这个流、获取里面的实际目的地数据。


解决方案:将Flux转换为List的Mono

要拿到正确的列表数据,我们需要先把Flux中的元素收集成一个List,再放到ResponseData里。修改后的代码如下:

修改后的处理器函数

public Mono<ServerResponse> findAll(ServerRequest request) {
    // 先把Flux收集为List的Mono,再构建ResponseData
    return destinationService.findAll()
            .collectList()
            .map(this::buildResponseData)
            .flatMap(responseData -> ServerResponse.ok().bodyValue(responseData));
}

修改后的buildResponseData方法

// 参数从Flux<Destination>改为List<Destination>
private ResponseData buildResponseData(List<Destination> destinations) {
    ResponseData responseData = new ResponseData();
    responseData.setStatus(HttpStatus.OK.value());
    responseData.setCode(DESTINATION_LIST_SUCCESS_CODE);
    responseData.setMessage(DESTINATION_LIST_SUCCESS_MESSAGE);
    responseData.setData(destinations);
    return responseData;
}

修改后的正确返回结果

调整后,你就能得到预期的目的地列表了:

{
    "status":200,
    "code":"destination_list_success",
    "message":"Retorno realizado com sucesso",
    "data":[
        {"id":1,"local":"Paris"},
        {"id":2,"local":"London"}
    ]
}

补充说明

如果需要处理大数据量,不想一次性把所有元素加载到内存中,可以考虑直接返回Flux<Destination>(不用ResponseData包装),这样WebFlux会流式输出数据。但如果必须用统一的ResponseData包装,上面的方法是最稳妥的——因为ResponseData是同步的包装对象,需要实际的数据集合而非反应式流对象。

内容的提问来源于stack exchange,提问作者Fabio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:03:50