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

Spring WebFlux+Thymeleaf如何显示响应式集合的真实大小?

问题原因分析

你使用的IReactiveDataDriverContextVariable是Thymeleaf的响应式数据驱动渲染组件,设置的批次大小为1意味着Thymeleaf会从Flux中每次拉取1条数据进行渲染。此时#lists.size(items)获取的是当前批次的数据集大小(也就是你看到的1),而非整个Flux的总数据量。


解决方案

方案1:后端接口返回总条数(最优)

如果你的REST后端支持返回总数据量(比如分页接口会附带totalCount字段),可以直接在请求时获取总条数并传入Model:

控制器代码

@GetMapping("/counterparties")
public String init(Model model) {
    // 假设后端返回包含总条数和数据的响应对象(自定义PageResponse类)
    Mono<PageResponse<Counterpart>> responseMono = webClient
            .get()
            .uri(uriBuilder -> uriBuilder.path("/findAllCounterpart").build())
            .retrieve()
            .bodyToMono(new ParameterizedTypeReference<PageResponse<Counterpart>>() {});

    // 拆分总条数和流式数据
    Mono<Integer> totalCountMono = responseMono.map(PageResponse::getTotal);
    Flux<Counterpart> dataFlux = responseMono.flatMapIterable(PageResponse::getData);

    // 保持响应式流式渲染
    IReactiveDataDriverContextVariable reactiveData = new ReactiveDataDriverContextVariable(dataFlux, 1);
    model.addAttribute("items", reactiveData);
    // 传入总条数
    model.addAttribute("totalRows", totalCountMono);

    return "counterparties.html";
}

// 自定义PageResponse示例
class PageResponse<T> {
    private int total;
    private List<T> data;
    // getter/setter
}

模板代码

<label th:text="'total rows: ' + ${totalRows}">rows number in table</label>

方案2:收集Flux为List(放弃流式渲染)

如果后端不支持返回总条数,可以将Flux收集为Mono,一次性获取总条数,但会失去响应式流式渲染的优势:

控制器代码

@GetMapping("/counterparties")
public String init(Model model) {
    Mono<List<Counterpart>> itemsMono = webClient
            .get()
            .uri(uriBuilder -> uriBuilder.path("/findAllCounterpart").build())
            .retrieve()
            .bodyToFlux(Counterpart.class)
            .collectList();

    model.addAttribute("items", itemsMono);
    // 直接从List获取大小
    model.addAttribute("totalRows", itemsMono.map(List::size));

    return "counterparties.html";
}

模板代码

<label th:text="'total rows: ' + ${totalRows}">rows number in table</label>

方案3:前端JS实时统计(保留流式渲染)

无需修改后端,通过JavaScript监听表格行的添加,实时统计总条数:

模板代码

<label id="totalRowsLabel">total rows: 0</label>

<table>
    <!-- 原表格内容不变 -->
    <thead>
    <tr>
        <td>ID</td>
        <td>Name</td>
        <td>Alive</td>
    </tr>
    </thead>
    <tbody>
    <tr th:each="item : ${items}">
        <td th:text="${item.counterpartID}" />
        <td th:text="${item.counterpartName}" />
        <td th:text="${item.alive}"/>
    </tr>
    </tbody>
</table>

<script>
    const tbody = document.querySelector('table tbody');
    const totalLabel = document.getElementById('totalRowsLabel');

    // 更新计数函数
    const updateTotal = () => {
        const rowCount = tbody.querySelectorAll('tr').length;
        totalLabel.textContent = `total rows: ${rowCount}`;
    };

    // 初始更新
    updateTotal();
    // 监听行的添加/移除
    const observer = new MutationObserver(updateTotal);
    observer.observe(tbody, { childList: true });
</script>

方案对比
方案优点缺点
方案1保留流式渲染,总条数准确依赖后端支持返回总条数
方案2实现简单,总条数准确数据量大时页面加载慢,失去响应式优势
方案3无需后端修改,保留流式渲染总条数随数据推送逐步更新,存在延迟

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:15:34