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

Spring Cache缓存方法疑似被绕过?后端请求异常频繁求助排查

问题排查与解决方案

核心原因分析

你遇到的问题核心在于缓存的对象是惰性求值类型(如Reactive的Flux/Mono),而非实际数据集合:

  • Web应用的getFooBars方法被@Cacheable缓存后,确实只执行一次(所以每15分钟才打印一次"CACHE MISS"),但方法返回的是WebClient请求得到的Flux或Mono这类Reactive容器对象,而非直接返回数据集合。
  • Thymeleaf每次渲染页面调用toIterable()时,都会触发Reactive容器的订阅操作,导致WebClient重新发起HTTP请求到后端服务,所以后端每次刷新都打印"backend getting foobars"。

排查验证步骤

  • 打印getFooBars方法返回值的哈希码:在方法内添加System.out.println("返回对象哈希码:" + result.hashCode());,确认缓存命中时返回的是同一个对象。
  • 检查返回类型:确认getFooBars的返回值是否为Flux<FooBar>、Mono<List<FooBar>>这类惰性类型,而非List<FooBar>这类直接的数据集合。

解决方案

修改getFooBars方法,将Reactive类型转换为实际的非惰性数据集合后再返回,确保缓存的是最终数据而非容器:

@Cacheable("foobar")
public List<FooBar> getFooBars() {
    System.out.println("CACHE MISS");
    // 将WebClient的Reactive结果转换为实际List
    return webClient.get()
            .uri("/api/foobars")
            .retrieve()
            .bodyToFlux(FooBar.class)
            .collectList() // 收集为List
            .block(); // 阻塞获取结果(适配Thymeleaf同步渲染场景)
}

同时修改Thymeleaf表达式,直接遍历List即可:

<th:block th:each="fooBar : ${@fooBarRepository.getFooBars}">
    <!-- 渲染逻辑 -->
</th:block>

其他排查方向

  • 确认Spring Cache代理生效:检查WebAppFooBarRepositoryImpl是否被Spring管理(如添加@Repository/@Component注解),且没有被内部方法调用绕过代理。
  • 验证Coffee Boots配置:确认foobar缓存的过期策略是否正确应用(从"CACHE MISS"频率来看,配置已生效)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:39:55