Spring Boot 的 @Cacheable 可直接以 Pageable 对象作为缓存键,因其标准实现(如 PageRequest)已重写 equals() 和 hashCode(),能精准区分不同页码、页大小及排序条件,实现按页粒度的高效缓存。
spring boot 的 `@cacheable` 可直接以 `pageable` 对象作为缓存键,因其标准实现(如 `pagerequest`)已重写 `equals()` 和 `hashcode()`,能精准区分不同页码、页大小及排序条件,实现按页粒度的高效缓存。
在 Spring Boot 中为分页查询方法启用缓存时,关键在于理解缓存键(key)的生成逻辑。你无需手动拼接字符串或提取 page、size、sort 字段——Spring 的缓存抽象会自动将 Pageable 参数作为默认缓存键,前提是该对象具备可靠的相等性判断能力。
幸运的是,Spring Data 提供的 Pageable 实现(如 PageRequest.of(0, 20, Sort.by("name")))已完整重写了 equals() 和 hashCode() 方法,确保语义相同的分页请求(例如:第 0 页、每页 20 条、按 name 升序)始终生成一致的哈希值,而不同参数组合(如第 1 页或按 price 排序)则产生独立缓存条目。
因此,以下写法完全合法且推荐:
@Service
public class MarketServiceImpl implements MarketService {
@Autowired
private MarketDao marketDao;
@Cacheable(value = "marketData")
public Page<StockMarkets> findAllMarket(Pageable pageable) {
return marketDao.findAll(pageable);
}
}✅ 无需显式指定 key 属性:Spring 默认使用全部方法参数(此处即 pageable 实例)构建缓存键;
✅ 天然支持多维度区分:页码(getPageNumber())、页大小(getPageSize())、排序字段与方向(getSort())均参与哈希计算;
✅ 线程安全 & 无副作用:PageRequest 是不可变对象,可安全用作并发环境下的缓存键。
⚠️ 注意事项:
- 避免传入自定义 Pageable 实现且未重写 equals/hashCode,否则会导致缓存失效或冲突;
- 若需排除某些非业务属性(如 Pageable 的 offset 计算值),应坚持使用 PageRequest.of(...) 而非手动构造;
- 缓存容量需合理配置(如使用 Caffeine 时设置 maximumSize),防止高频分页参数导致内存膨胀;
- 结合 @CacheEvict 清理关联缓存(例如新增/删除商品后,清除 marketData 中所有分页结果)。
综上,Spring Boot 对 Pageable 的缓存支持简洁而健壮——你只需信任其默认行为,专注业务逻辑,即可获得开箱即用的分页级缓存能力。

















