news 2026/6/19 7:52:18

使用Spring自带的缓存注解维护数据一致性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用Spring自带的缓存注解维护数据一致性

简介

Cache(缓存),已经是项目中不可缺失的存在,登录时,存储用户信息、操作权限、Token 等,高并发场景,存储热点信息、实时信息等。按照类型分类,可分为本地缓存和分布式缓存,前者重启服务失效,后者可以持久化,按照设置的过期时间或策略失效。

一旦项目中需要使用到缓存,就需要考虑到数据一致性问题,即缓存数据与数据库数据的一致性问题,本文介绍在 Spring Boot 项目中,如何使用 Spring 自带的注解来进行数据一致性的维护。

整合

Spring 自带了缓存维护的注解,如果你的项目就是 Spring/Spring Boot 项目,不需要额外引入依赖

但如果你需要缓存不会因项目重启而失效,可以引入 Redis,把 Redis 当作缓存容器,需引入 Redis 依赖。基本所有的项目都会用到 Redis,当然引入了就需要保证系统与 Redis 的连通。

<!-- 引入 Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

在项目中创建一个 Redis 缓存配置类,里面对缓存进行统一的配置,如过期时间等。

importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;importorg.springframework.data.redis.cache.RedisCacheManager;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializationContext;importorg.springframework.data.redis.serializer.StringRedisSerializer;importjava.time.Duration;/** * Redis 缓存配置 */@Configuration@EnableCachingpublicclassRedisCacheConfig{@BeanpublicRedisCacheManagercacheManager(RedisConnectionFactoryconnectionFactory){RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(newStringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(newGenericJackson2JsonRedisSerializer()));returnRedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();}}

配置文件中,添加 Redis 配置。

spring:redis:host:localhostport:6379

使用

配合下面几个注解使用,可以加在接口上,如下,cacheNames是设置缓存名称,key设置缓存的 key 值,可以用#与方法入参关联,如#id表示 key 值取自方法入参 id 的值。

  • @Cacheable(cacheNames = “缓存名”, key = “#id”):添加缓存;

  • @CachePut(cacheNames = “缓存名”, key = “#id”):执行方法后,添加缓存;

  • @CacheEvict(cacheNames = “缓存名”, key = “#id”):使缓存失效;

需要注意的是,这套缓存作用的机制是,关联方法入参与返回,当方法入参相同时,返回缓存中的结果,不再执行代码。所以只有相同的入参才能用得上缓存。

验证

创建下面这四个接口,查询方法添加缓存,新增方法执行后添加缓存,删除和更新方法删除缓存。

importorg.example.service.CacheService;importorg.springframework.cache.annotation.CacheEvict;importorg.springframework.cache.annotation.CachePut;importorg.springframework.cache.annotation.Cacheable;importorg.springframework.web.bind.annotation.*;importjavax.annotation.Resource;@RestController@RequestMapping("/cache")publicclassCacheController{@ResourceprivateCacheServicecacheService;@GetMapping("/getOne")@Cacheable(cacheNames="cacheName",key="#id")publicStringgetOne(@RequestParamStringid){returncacheService.getOne();}@PostMapping("/createOne")@CachePut(cacheNames="cacheName",key="#id")publicStringcreateOne(@RequestParamStringid){returncacheService.createOne();}@PostMapping("/deleteOne")@CacheEvict(cacheNames="cacheName",key="#id")publicStringdeleteOne(@RequestParamStringid){returncacheService.deleteOne();}@PostMapping("/updateOne")@CacheEvict(cacheNames="cacheName",key="#id",allEntries=true)publicStringupdateOne(@RequestParamStringid){returncacheService.updateOne();}}

对应的实现类代码。

importorg.springframework.stereotype.Service;@ServicepublicclassCacheServiceImplimplementsCacheService{@OverridepublicStringgetOne(){return"Select is a cache data.";}@OverridepublicStringcreateOne(){return"Create is a cache data.";}@OverridepublicStringdeleteOne(){return"Deleted is a cache data.";}@OverridepublicStringupdateOne(){return"Updated is a cache data.";}}

启动项目,测试一下。

首次查询,断点卡在查询方法实现类这里,执行了实现类方法。

再次查询,直接返回了结果。

Redis 中增加了一个缓存。

参数换一下,传入 id=1。

发送请求,断点卡住了,说明没走缓存。

新增了一个 id=1 的缓存。

再试下更新方法,更新 id=1 的记录。

发送请求,查看 Redis,缓存都没了。

本来可以只让符合条件的,即 id=1 的缓存失效,上面都失效了,是因为我在更新方法的注解上额外加了一个属性。

allEntries = true,名称相同的所有缓存都失效,默认 false。

再试下,删除方法我没加这个属性。

调用删除方法,删除 id=1 的记录。

这回只有 id=1 的缓存被删除。

另外再试下创建方法,创建方法会再执行完创建方法后,主动将返回值添加到缓存中。

实际开发中,可以在某个创建接口完成后,将完整的对象数据返回,无缝衔接,就不用首次查询还要走一遍实现层。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 12:15:47

全息感知应用创新:MediaPipe Holistic在医疗康复中的使用

全息感知应用创新&#xff1a;MediaPipe Holistic在医疗康复中的使用 1. 引言&#xff1a;AI 全身全息感知的技术演进与医疗价值 随着人工智能在计算机视觉领域的持续突破&#xff0c;全身多模态感知技术正从娱乐、虚拟现实等消费级场景逐步渗透至医疗健康领域。传统的康复评…

作者头像 李华
网站建设 2026/6/15 0:27:27

Holistic Tracking技术揭秘:33个姿态点检测算法解析

Holistic Tracking技术揭秘&#xff1a;33个姿态点检测算法解析 1. 技术背景与核心挑战 在计算机视觉领域&#xff0c;人体动作理解一直是极具挑战性的研究方向。传统方法通常将面部、手部和身体作为独立模块处理&#xff0c;导致系统复杂度高、数据对齐困难、实时性差。随着…

作者头像 李华
网站建设 2026/5/31 5:21:06

OpCore Simplify终极教程:3步快速生成完美EFI配置

OpCore Simplify终极教程&#xff1a;3步快速生成完美EFI配置 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify OpCore Simplify是一款专业的OpenCore E…

作者头像 李华
网站建设 2026/6/15 0:28:02

手把手教你部署IndexTTS2,从下载到语音输出全过程

手把手教你部署IndexTTS2&#xff0c;从下载到语音输出全过程 1. 引言&#xff1a;为什么选择IndexTTS2 V23版本&#xff1f; 在当前语音合成&#xff08;Text-to-Speech, TTS&#xff09;技术快速发展的背景下&#xff0c;用户对语音自然度、情感表达和响应速度的要求日益提…

作者头像 李华
网站建设 2026/6/15 2:00:43

BiliTools AI视频总结终极指南:3分钟掌握B站视频精华内容

BiliTools AI视频总结终极指南&#xff1a;3分钟掌握B站视频精华内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持视频、音乐、番剧、课程下载……持续更新 项目地址: https://gitcode.com/GitHub_Trending/bilit/B…

作者头像 李华
网站建设 2026/6/15 2:01:40

猫抓Cat-Catch:网页资源智能捕获完全手册

猫抓Cat-Catch&#xff1a;网页资源智能捕获完全手册 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾遇到过这样的困扰&#xff1a;网页上精彩的视频无法保存&#xff0c;在线课程受限于平台…

作者头像 李华