系列十、SpringBoot + MyBatis + Redis实现分布式缓存(基于注解方式)

一、概述

        上篇文章 系列九、SpringBoot + MyBatis + Redis实现分布式缓存 介绍了基于xml方式实现分布式缓存的效果,当前大家使用的技术栈基本是springboot+各种框架的组合,而springboot显著的一个特点就是去xml配置,那么在无xml配置的情形下,又该如何实现分布式缓存呢?请看下面的代码实战

二、代码实战

2.1、分布式缓存相关的注解

        基于注解方式的分布式缓存,主要涉及到如下几个注解:

        (1)@EnableCaching:一般标注在配置类上,表示开启Spring的缓存,如果不加此注解的话Spring自带的缓存将不生效;

        (2)@CacheConfig(cacheNames = "xxx"):一般标注在service类上,用于配置cache的名字,建议以当前service类的全路径名作为cache的名字;

        (3)@Cacheable:一般标识在service层的查询方法上,表示将一个方法的返回值缓存起来,  默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值,如果查询 方法无参数,则会使用默认的key,即SimpleKey [];

        (4)@CachePut(key = "#department.id"):一般加在service层的更新方法上(update),当数据库中的数据更新后,缓存中的数据也要跟着更新,使用此注解,可以将方法的返回值 自动更新到已经存在的key上

        (5)@CacheEvict:一般加在service层的删除方法上,当数据库中的数据删除后,相关的缓存也会被删除,使用该注解的时候,也可以配置按照某种条件删除(某种条件:@CacheEvict注解中的条件,例如:value、cacheNames、key、keyGenerator...)

2.2、项目概览

2.3、pom

<dependencies><!-- springboot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><!-- 数据源 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 工具 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.21</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.25</version></dependency></dependencies>

2.4、yml

server:port: 9999spring:redis:host: port: 6379database: 0password: 123456datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/20231018_redis?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMTusername: rootpassword: 123456mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: org.stat.entity.modelconfiguration:map-underscore-to-camel-case: truelogging:level:org:star:mapper: debug

2.5、主启动

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 12:44* @Description:**/
@MapperScan(basePackages = "org.star.mapper")
@SpringBootApplication
public class SpringbootRedisDistributeCacheAnnotationApplication {public static void main(String[] args) {SpringApplication.run(SpringbootRedisDistributeCacheAnnotationApplication.class, args);}}

2.6、MyRedisConfig

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 15:28* @Description:* @EnableCaching的作用:开启Spring的缓存,如果不加此注解的话Spring自带的缓存将不生效**/
@EnableCaching
@Configuration
public class MyRedisConfig {/*** RedisTemplate k v 序列化** @param connectionFactory* @return*/@Beanpublic RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(RedisSerializer.string());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.afterPropertiesSet();return redisTemplate;}@Beanpublic RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()// 设置默认的超时时间为2小时.entryTtl(Duration.ofHours(2)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))// 设置默认的缓存前缀.prefixCacheNameWith("REDIS_CACHE_");return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);}}

2.7、DepartmentDO

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 12:48* @Description:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class DepartmentDO implements Serializable {/*** 编号*/private Integer id;/*** 部门名称*/private String departmentName;}

2.8、DepartmentMapper.java

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 12:50* @Description:*/
public interface DepartmentMapper {/*** 查询所有部门* @return*/List<DepartmentDO> listAllDepartment();/*** 根据id查询部门信息* @param id* @return*/DepartmentDO getDepartmentById(Integer id);/*** 根据id和departmentName查询部门* @param id* @param departmentName* @return*/DepartmentDO getDepartment(Integer id,String departmentName);/*** 更新Department* @param department* @return*/int updateDepartment(DepartmentDO department);/*** 删除部门* @param id*/void deleteDepartment(Integer id);
}

2.9、DepartmentMapper.xml

<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="org.star.mapper.DepartmentMapper"><select id="listAllDepartment" resultType="org.star.entity.model.DepartmentDO">select id,department_name from department</select><select id="getDepartmentById" resultType="org.star.entity.model.DepartmentDO">select id,department_name from department where id = #{id}</select><select id="getDepartment" resultType="org.star.entity.model.DepartmentDO">select id,department_name from department where id = #{id} and department_name = #{departmentName}</select><update id="updateDepartment" useGeneratedKeys="true" keyProperty="id">update department set department_name = #{departmentName} where id = #{id}<selectKey resultType="org.star.entity.model.DepartmentDO" order="AFTER" keyProperty="id">select id,department_name from department where id = #{id}</selectKey></update><delete id="deleteDepartment">delete from department where id = #{id}</delete></mapper>

2.10、DepartmentService

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 20:00* @Description:* 基于注解的分布式缓存,redis中key的生成规则:${prefixCacheNameWith} + "_" + ${cacheNames} + "_" + ${key}*      说明:prefixCacheNameWith为RedisCacheManager中配置的前缀*      举例:*          (1)listAllDepartment ===> REDIS_CACHE_org.star.service.DepartmentService::SimpleKey []*          (2)getDepartmentById ===> REDIS_CACHE_org.star.service.DepartmentService::1*          (3)getDepartment ===> REDIS_CACHE_org.star.service.DepartmentService::SimpleKey [1,研发部]**/
@Service
@CacheConfig(cacheNames = "org.star.service.DepartmentService")
public class DepartmentService {@Resourceprivate DepartmentMapper departmentMapper;/*** @return* @Cacheable的作用:*      @Cacheable注解一般加在查询方法上,表示将一个方法的返回值缓存起来,* 默认情况下,缓存的key就是方法的参数,缓存的value就是方法的返回值,如果查询* 方法无参数,则会使用默认的key,即SimpleKey []*/@Cacheablepublic List<DepartmentDO> listAllDepartment() {List<DepartmentDO> departments = departmentMapper.listAllDepartment();return departments;}/*** 对于只有一个参数的查询方法,其key位id对应的值* @param id* @return*/@Cacheablepublic DepartmentDO getDepartmentById(Integer id) {return departmentMapper.getDepartmentById(id);}/**** 对于有多个参数的查询方法,其key为所有的参数,如果想修改,可以单独指定,例如:@Cacheable(key = "#id")* @param id* @param departmentName* @return*/@Cacheablepublic DepartmentDO getDepartment(Integer id,String departmentName) {return departmentMapper.getDepartment(id,departmentName);}/*** @CachePut作用:*      @CachePut注解一般加在更新方法上(update),当数据库中的数据更新后,缓存中的数据也要跟着更新,使用此注解,可以将方法的返回值*      自动更新到已经存在的key上,示例如下:* @param department* @return*/@CachePut(key = "#department.id")public DepartmentDO updateDepartment(DepartmentDO department) {departmentMapper.updateDepartment(department);return department;}/*** @CacheEvict()作用:*      @CacheEvict()注解一般加在删除方法上,当数据库中的数据删除后,相关的缓存也会被删除,使用该注解的时候,也可以配置按照某种条件*      删除(某种条件:@CacheEvict注解中的条件,例如:value、cacheNames、key、keyGenerator...)* @param id*/@CacheEvictpublic void deleteDepartment(Integer id) {departmentMapper.deleteDepartment(id);}}

2.11、DepartmentServiceTest

/*** @Author : 一叶浮萍归大海* @Date: 2023/12/10 20:07* @Description:*/
@SpringBootTest
public class DepartmentServiceTest {@Resourceprivate DepartmentService departmentService;@Testpublic void listAllDepartmentTest() {List<DepartmentDO> departments1 = departmentService.listAllDepartment();System.out.println("departments1 = " + departments1);System.out.println("=============================");List<DepartmentDO> departments2 = departmentService.listAllDepartment();System.out.println("departments2 = " + departments2);}@Testpublic void getDepartmentByIdTest() {DepartmentDO department1 = departmentService.getDepartmentById(1);System.out.println("department1 = " + department1);System.out.println("========================");DepartmentDO department2 = departmentService.getDepartmentById(1);System.out.println("department2 = " + department2);}@Testpublic void getDepartmentTest() {DepartmentDO department1 = departmentService.getDepartment(1, "研发部");System.out.println("department1 = " + department1);System.out.println("============================");DepartmentDO department2 = departmentService.getDepartment(1, "研发部");System.out.println("department2 = " + department2);}@Testpublic void updateDepartmentTest() {DepartmentDO department = new DepartmentDO().setDepartmentName("研发部444").setId(1);DepartmentDO updatedDepartment = departmentService.updateDepartment(department);System.out.println("updatedDepartment = " + updatedDepartment);}@Testpublic void deleteDepartmentTest() {departmentService.deleteDepartment(1);}}

2.12、测试

2.12.1、listAllDepartmentTest

2.12.2、 getDepartmentByIdTest

2.12.3、getDepartmentTest

2.12.4、 updateDepartmentTest

2.12.5、 deleteDepartmentTest

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/215684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

界面控件DevExpress中文教程 - 如何用Office File API组件填充PDF表单

DevExpress Office File API是一个专为C#, VB.NET 和 ASP.NET等开发人员提供的非可视化.NET库。有了这个库&#xff0c;不用安装Microsoft Office&#xff0c;就可以完全自动处理Excel、Word等文档。开发人员使用一个非常易于操作的API就可以生成XLS, XLSx, DOC, DOCx, RTF, CS…

基于SpringBoot的就业信息管理系统设计与实现(源码+数据库+文档)

摘 要 在新冠肺炎疫情的影响下&#xff0c;大学生的就业问题已经变成了一个引起人们普遍重视的社会焦点问题。在这次疫情的冲击之下&#xff0c;大学生的就业市场的供求双方都受到了不同程度的影响&#xff0c;大学生的就业情况并不十分乐观。目前&#xff0c;各种招聘平台上…

云原生之使用Docker部署Mariadb数据库

目录 一、什么是云原生 二、Docker介绍 三、Mariadb数据库介绍 四、如何使用Docker部署Mariadb数据库 一、什么是云原生 云原生是一种综合性的技术和方法论&#xff0c;旨在对应用程序进行全生命周期的管理&#xff0c;包括开发、部署、运行和扩展。它倡导将应用程序设计为…

moviepy基本参数用法大全

阅读本文档的前置说明&#xff1a; 本文档用于讲解Python的moviepy库的自带函数的用法&#xff0c;主要目的是讲一下每个函数的每个参数的含义&#xff0c;无需一开始就全部掌握&#xff0c;粗略看一下就行&#xff0c;可以在后面自己开发过程&#xff0c;遇到不会用的函数再回…

数据库——字段拆分与合并

一、GP或PostgreSQL 1.字段拆分成行 unnest(string_to_array(test, ,)) 例如某一字段值为"a,b,c,d"&#xff0c;使用string_to_array将其拆分为数组&#xff0c;然后使用unnest将数组平铺成一张表 SELECT unnest(string_to_array(555,666,777, ,)) 2.字段拆分成列…

【EI征稿倒计时3天】第四届IEEE信息科学与教育国际学术会议(ICISE-IE 2023)

第四届IEEE信息科学与教育国际学术会议(ICISE-IE 2023) 2023 4th International Conference on Information Science and Education&#xff08;ICISE-IE 2023&#xff09; ICISE-IE2024已上线岭南师范学院官网&#xff08;点击查看&#xff09; 第四届IEEE信息科学与教育国…

@Transactional失效问题

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 关于Transactional 日…

解读 | 为什么有很多名人让人们警惕人工智能

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xff1a;https://t.zsxq.com/0aiNxERDq 这个话题总能引起很…

六、ZGC深度剖析

一、引言 对于Java 程序员来说&#xff0c;JVM 帮助我们做了很多事情。 JVM是虚拟机&#xff0c;能够识别字节码&#xff0c;就是class文件或者你打包的jar文件&#xff0c;运行在操作系统上。 JVM帮我们实现了跨平台&#xff0c;你只需要编译一次&#xff0c;就可以在不同的…

在线课堂知识付费小程序源码系统 开发组合PHP+MySQL:用手机随时随地地学习,讲师亲自在线授业解惑 带安装部署教程

近年来&#xff0c;人们对于学习的需求也日益增加。传统的课堂教学已经无法满足人们的学习需求&#xff0c;而在线课堂则能够让人们随时随地地进行学习。同时&#xff0c;随着知识付费的兴起&#xff0c;越来越多的讲师也愿意将自己的知识和经验分享给更多的人。因此&#xff0…

如何管理医疗设备用电?这才是最佳方法!

随着社会对可持续发展和环保的关注不断上升&#xff0c;蓄电池监控系统作为能源存储和管理的关键技术&#xff0c;正在崭露头角。 蓄电池监控系统不仅为能源行业带来了新的可能性&#xff0c;同时也为各个领域的能源使用者提供了更加智能、高效的解决方案。 客户案例 工业生产…

ansible部署安装Tomcat

我们需要用到的文件jdk以及tomcat安装包 下载链接:https://pan.baidu.com/s/1sjG8Yl8k-SUbOv7KwKXZMA 提取码&#xff1a;t71z 准备n台机器&#xff08;我这里就简单部署三台机器&#xff09; ansible的安装部署以及配置可以看博主之前的文章自动化运维工具-ansible部署 ansib…

建筑可视化数据大屏汇总,UI源文件(PC端大屏设计)

酷炫的大屏设计让数据更好的展现&#xff0c;方便业务人员分析数据&#xff0c;辅助领导决策。现在分享大屏Photoshop源文件&#xff0c;以下为部分截图示意。 划重点&#xff1a;文末可获得完整素材包~ 01 科技建筑平台数据可视化 02 建筑公司可视化数据汇总平台 03 深蓝…

JVM虚拟机系统性学习-对象存活判断算法、对象引用类型和垃圾清除算法

垃圾回收 在 JVM 中需要对没有被引用的对象&#xff0c;也就是垃圾对象进行垃圾回收 对象存活判断算法 判断对象存活有两种方式&#xff1a;引用计数法、可达性分析算法 引用计数法 引用计数法通过记录每个对象被引用的次数&#xff0c;例如对象 A 被引用 1 次&#xff0c…

多示例VS多标签VS多示例多标签-week2

一、多示例 多示例学习属于弱监督学习中的一种&#xff0c;在对模型进行训练时&#xff0c;我们需要把训练数据分成正负包&#xff0c;再将每个包分成大小相同的示例&#xff0c;并且我们只对包的正负进行标注&#xff0c;而不对示例进行分类。当某个包被标识为正时&#xff0c…

Python常见面试知识总结(二):数据结构、类方法及异常处理

【十三】Python中assert的作用&#xff1f; Python中assert&#xff08;断言&#xff09;用于判断一个表达式&#xff0c;在表达式条件为 f a l s e false false的时候触发异常。 断言可以在条件不满足程序运行的情况下直接返回错误&#xff0c;而不必等待程序运行后出现崩溃…

【项目管理】如何用思维导图做计划?

思维导图是一种可视化的思维工具&#xff0c;它可以让我们的思考过程变得很直观。它可以帮助我们考虑到计划的各个方方面面&#xff0c;确定各要素之间的关系。 思维导图总结功能很强&#xff0c;完成计划后&#xff0c;可以用思维导图进行总结&#xff0c;为下一次做计划积累…

使用【ShardingSphere】分库分表

前言 ShardingSphere可以支撑分库分表&#xff0c;刚果商城采用了垂直分库&#xff08;根据不同业务拆分数据库&#xff09;&#xff0c;因此此文章只演示水平分表。 垂直分库 不同业务拆分为不同的数据库&#xff08;例如商城业务&#xff09; 水平分表 分表可以通过将大表拆…

移液器吸头材质选择——PFA吸头在半导体化工行业的应用

PFA吸头是一种高性能移液器配件&#xff0c;这种材料具有优异的耐化学品、耐热和电绝缘性能&#xff0c;使得PFA吸头在应用中表现出色。那么它有哪些特点呢&#xff1f; 首先&#xff0c;PFA吸头具有卓越的耐化学腐蚀性能。无论是酸性溶液、碱性溶液还是有机溶剂&#xff0c;P…

如何用CHAT帮你提高工作效率?

问CHAT&#xff1a;从规范项目管理流程交付&#xff0c;分别对项目信息安全管理&#xff0c;项目预算管理和项目采购管理三个方面提建议 CHAT回复&#xff1a; 项目信息安全管理: 1. 制定详细的信息安全政策&#xff0c;所有参与项目的员工必须遵守&#xff0c;对其中涉及敏感…