目录 :
- [Spring Boot 实现 "Redis缓存管理" :](#Spring Boot 实现 "Redis缓存管理" :)
-
- [一、Spring Boot 支持的 "缓存组件" ( 如果 "没有" 明确指定使用自定义的 "cacheManager "或 "cacheResolver" ,此时 SpringBoot会按照"预先定义的顺序" 启动一个默认的 "缓存组件" 来进行 "缓存管理" )](#一、Spring Boot 支持的 "缓存组件" ( 如果 “没有” 明确指定使用自定义的 "cacheManager "或 "cacheResolver" ,此时 SpringBoot会按照“预先定义的顺序” 启动一个默认的 “缓存组件” 来进行 "缓存管理" ))
- [二、基于 "注解" 的 "Redis缓存管理" ( 是在"默认缓存管理" 项目的基础上,进行关于Redis缓存内容的 添加 ) - 案例演示 :](#二、基于 "注解" 的 "Redis缓存管理" ( 是在"默认缓存管理" 项目的基础上,进行关于Redis缓存内容的 添加 ) - 案例演示 :)
-
- [① 添加 "Spring Data Redis 依赖启动器" ( 之前是用SpringBoot默认的 "Simple : 缓存组件" 来 进行 "缓存管理" , 现在选择使用"Redis"缓存组件来进行 "缓存管理" ,此时 将"缓存数据" 存储在 "Redis数据库"中 )](#① 添加 "Spring Data Redis 依赖启动器" ( 之前是用SpringBoot默认的 "Simple : 缓存组件" 来 进行 "缓存管理" , 现在选择使用"Redis"缓存组件来进行 "缓存管理" ,此时 将"缓存数据" 存储在 "Redis数据库"中 ))
- [② 添加 "Redis服务" 的 "连接配置信息"](#② 添加 "Redis服务" 的 "连接配置信息")
- [③ 使用@Cacheable、@CachePut、@CacheEvict注解 "定制缓存管理" ( 使用Redis缓存时,"缓存管理"的操作还是和"之前的操作"一样,用"Redis"缓存 可以理解为 : 此时将"缓存数据" 存储在 "Redis数据库"中, 而不是 存储在"内存"中 )](#③ 使用@Cacheable、@CachePut、@CacheEvict注解 "定制缓存管理" ( 使用Redis缓存时,“缓存管理”的操作还是和"之前的操作"一样,用"Redis"缓存 可以理解为 : 此时将”缓存数据“ 存储在 "Redis数据库"中, 而不是 存储在"内存"中 ))
- [④ 将"缓存对象" 实现 "序列化" ( 实现序列化接口 : Serializable 接口 )](#④ 将"缓存对象" 实现 "序列化" ( 实现序列化接口 : Serializable 接口 ))
- [⑤ 设置 "Redis缓存数据" 的 "有效期"](#⑤ 设置 "Redis缓存数据" 的 "有效期")
- [⑥ 基于注解的 "Redis查询" "缓存测试"](#⑥ 基于注解的 "Redis查询" "缓存测试")
- [三、基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理"](#三、基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理")
-
- [31. "RedisTemplate类"的 功能介绍 ( 通过该类可以在Java中 "操作Redis数据库 " )](#31. "RedisTemplate类"的 功能介绍 ( 通过该类可以在Java中 "操作Redis数据库 " ))
- [3.2 基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理" - 案例演示 :](#3.2 基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理" - 案例演示 :)
-
- [① 准备数据](#① 准备数据)
- [② 创建项目 + 开启Mysql服务 + 开启Redis服务](#② 创建项目 + 开启Mysql服务 + 开启Redis服务)
- [③ 在配置"全局配置文件" 中 "配置信息"](#③ 在配置"全局配置文件" 中 "配置信息")
- [④ 编写 "数据库表" 对应的 "实体类" ( 要实现"序列化" )](#④ 编写 “数据库表” 对应的 “实体类” ( 要实现"序列化" ))
- [⑤ 编写 "操作数据库" 的 Repository接口文件 ( 通过该接口中的方法来 操作"Mysql数据库" )](#⑤ 编写 “操作数据库” 的 Repository接口文件 ( 通过该接口中的方法来 操作“Mysql数据库” ))
- [⑥ 编写 "控制器层"的 controller 对象](#⑥ 编写 "控制器层"的 controller 对象)
- [⑦ 编写 "业务操作层"的 service 对象](#⑦ 编写 "业务操作层"的 service 对象)
- [⑧ 基于 API ( RedisTemplate类 ) 的 "缓存管理" 测试](#⑧ 基于 API ( RedisTemplate类 ) 的 "缓存管理" 测试)
作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材 为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章
文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!
(侵权可联系我,进行删除,如果雷同,纯属巧合)
Spring Boot 实现 "Redis缓存管理" :
一、Spring Boot 支持的 "缓存组件" ( 如果 "没有" 明确指定使用自定义的 "cacheManager "或 "cacheResolver" ,此时 SpringBoot会按照"预先定义的顺序" 启动一个默认的 "缓存组件" 来进行 "缓存管理" )
在 Spring Boot 中,数据的 "管理存储"依赖于 Spring 框架中 cache ( 缓存 ) 相关的 :① org.springframework.cache. Cache 和
② org.springframework,cache .CacheManager ( 缓存管理器 )。如果程序中 没有 定义类型 为 cacheManager ( 缓存管理器 ) 的 Bean 组件 或者是 没有 名为 cacheResolver ( 缓存解析器 ) ,
Spring Boot 将 按照以下的顺序 来 选择并启动 缓存组件 :试 选择并启用以下缓存组件 ( 按照指定的顺序 ) :
① Generic
② JCache (JSR -107 ) ( EhCache 3 、Hazelcast 、Infinispan等 )
③ EhCache 2.x
④ Hazelcast
(5) Infinispan
(6) Couchbase
(7) Redis
(8) Caffeine
(9) Simple ( 默认"缓存组件" , SpringBoot 默认使用** 该"缓存组件"** 来 进行 "缓存管理" )
上面我们按照 Spring Boot 缓存组件的** 加载顺序** 列举了 支持的9种缓存组件,在项目中 添加某个缓存管理组件 (例如 Redis) 后 ,Spring Boot 项目会
选择并启用对应的** 缓存管理器**。如果项目中 同时添加了** 多个缓存组件** ,且 没有指定缓存管理器 /缓存解析器 ( cacheManager /cacheResolver ),那么 Spring Boot 按照 "指定的顺序 " 来 选择使用 其中的一个 "缓存组件 " 并进行"缓存管理" 。
在 Spring Boot默认的 "缓存管理" 项目 文章讲解 的 Spring Boot默认缓存管理中,** 没有添加 任何缓存管理组件却能 实现缓存管理**。这是因为开启缓存管理后 ,
如果 没有指定具体的"** cacheManager** "或 "cacheResolver " ,SpringBoot 将按照 指定的顺序选择并使用 "缓存组件" 。
如果没有任何缓存组件 ,会 默认使用最后一个** Simple 缓存组件** 进行管理 。Simple 缓存组件是 Spring Boot默认的** 缓存管理组件**,它** 默认使用内存中** 的 ConcurrentHashMap 进行 缓存存储 ,所以在没有添加任何第三方缓存组件 的情况下也可以实现内存中的缓存管理。
二、基于 "注解" 的 "Redis缓存管理" ( 是在"默认缓存管理" 项目的基础上,进行关于Redis缓存内容的 添加 ) - 案例演示 :
① 添加 "Spring Data Redis 依赖启动器" ( 之前是用SpringBoot默认的 "Simple : 缓存组件" 来 进行 "缓存管理" , 现在选择使用"Redis"缓存组件来进行 "缓存管理" ,此时 将"缓存数据" 存储在 "Redis数据库"中 )
Spring Boot默认的 "缓存管理" 项目 的基础上,( 先创建 好 默认 的"缓存管理 " 项目 ,再添加"Redis缓存"相关的代码 )添加
Spring Data Redis 依赖启动器 :
xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
② 添加 "Redis服务" 的 "连接配置信息"
使用类似 Redis 的 缓存组件进行** 缓存管理时,缓存数据并不是** 像 Spring Boot默认缓存管理那样** 存储在内存中** ,而是需要预先搭建 类似 Redis 服务 的数据仓库 进行缓存存储 。所以,这里首先需要 安装并开启 Redis 服务 : Redis的下载、安装 和 启动 ,然后 在项目的全局配置文件 : application.properties 中添加 Redis 服务的 连接配置信息 :
properties#Redis服务地址 spring.data.redis.host=127.0.0.1 #Redis服务器连接端口 spring.data.redis.port=6379 #Redis服务器连接密码(默认欸空) spring.data.redis.password=123456
③ 使用@Cacheable、@CachePut、@CacheEvict注解 "定制缓存管理" ( 使用Redis缓存时,"缓存管理"的操作还是和"之前的操作"一样,用"Redis"缓存 可以理解为 : 此时将"缓存数据" 存储在 "Redis数据库"中, 而不是 存储在"内存"中 )
在 CommentService类中分别使用** @Cacheable** 、@CachePut 、@CacheEvict3个注解 定制缓存管理 分别演示缓存数据的存储 、更新 和 删除 :
CommentService.java :
java@Service //加入到IOC容器中 public class CommentService { //sevice业务层 @Autowired private CommentRepository commentRepository; /** * @Cache()注解的使用 */ // #result : 表示获得 "方法" 的 "返回值" , 将查询到的数据,存储到"缓存空间"中 @Cacheable(cacheNames = "comment",key = "#comment_id",unless = "#result == null")//SPEL表达式来设置值 public Comment findById(int comment_id) { //调用commentRepository接口的祖先接口的方法来操作数据库 Optional<Comment> option = commentRepository.findById(comment_id); if (option.isPresent()) { //判断其中是否有数据 //获得其中的数据 Comment comment = option.get(); return comment; } return null; } /** * @CachePut()注解的使用 , 当更新数据库之后,同时将该方法的"返回值"来更新"缓存空间"中的数据 */ @CachePut(cacheNames = "comment",key = "#result.id") //设置该方法的"返回值"的id属性值为"key值" public Comment updateComment(int comment_id , String author) { Comment comment = findById(comment_id); comment.setAuthor(author); return commentRepository.save(comment); } /** * @CacheEvict()注解的使用 , 在删除数据库中数据成功后,同时也删除"缓存空间"中对应的"缓存数据" */ @CacheEvict(cacheNames = "comment") public void deleteComment(int comment_id) { commentRepository.deleteById(comment_id); //调用CrudRepository接口中的方法来操作数据库 } }
上面的代码 中,使用 @Cacheable 、@CachePut 、@CacheEvict 注解在数据查询 、更新 和删除 方法上进行了缓存管理 。在查询缓存 @Cacheable 注解中,定义了 "unless ="#result==null ""表示 "查询结果" 为空不进行缓存。
其他类的** 代码** :
CommentController.java :
java@Controller @ResponseBody //将相应给前端的"返回值" 转换为"指定类型" 后 存入到 "响应体" 中 public class CommentController { @Autowired private CommentService commentService; /** * 根据id来查询数据 */ @GetMapping("/findById/{id}") //id为"路径变量" public Comment findById(@PathVariable("id") int comment_id) { System.out.println("123123123"); Comment comment = commentService.findById(comment_id); return comment; } /** * 更新数据 */ @GetMapping("/updateComment/{id}") public Comment updateComment(@PathVariable("id") int comment_id,@PathVariable("author") String author) { Comment comment = commentService.updateComment(comment_id, author); return comment; } /** * 删除数据 */ @GetMapping("/delete/{id}") public void deleteComment(@PathVariable("id") int comment_id) { commentService.deleteComment(comment_id); } }
④ 将"缓存对象" 实现 "序列化" ( 实现序列化接口 : Serializable 接口 )
将"缓存对象 " ( Comment对象 ) 实现 "序列化" :
Comment.java :
java//指定该实现类映射的数据库表 @Entity(name = "t_comment") //设置ORM实体类, 并指定对应的表明 public class Comment implements Serializable { // 对"缓存对象"进行"序列化" //表示数据库表中主键对应的属性 @Id @GeneratedValue(strategy= GenerationType.IDENTITY) //设置主键的生成策略 (主键自增) private Integer id; @Column(name = "content") //指定映射的表字段名 private String content; @Column(name = "author") private String author; @Column(name = "a_id") private Integer aId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Integer getaId() { return aId; } public void setaId(Integer aId) { this.aId = aId; } @Override public String toString() { return "Comment{" + "id=" + id + ", content='" + content + '\'' + ", author='" + author + '\'' + ", aId=" + aId + '}'; } }
在进行 Redis缓存 时,如果 不对 "缓存对象" 进行 "序列化" ,在进行缓存 时,会报 IllegalArgumentException非法参数异常 ,提示信息要求对应的 Comment实体类 必须实现序列化 : 实现 JDK自带 的 序列化接口 : Serializable 接口 。
( 一些基本数据类型 ,不需要序列化 ,因为内部 已经默认实现了序列化接口 )
⑤ 设置 "Redis缓存数据" 的 "有效期"
设置 "Redis缓存数据 " 的 "有效期" :
application.properties :
propertiesspring.application.name=chapter_15 # mysql服务信息 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent=true spring.datasource.username=root spring.datasource.password=root #显示使用JPA进行"数据库查询"的SQL语句,用于展示操作的Sql语句 #这个属性决定了是否应该在控制台打印出SQL查询语句 spring.jpa.show-sql=true #Redis服务地址 spring.data.redis.host=127.0.0.1 #Redis服务器连接端口 spring.data.redis.port=6379 #Redis服务器连接密码(默认欸空) spring.data.redis.password=123456 #对基于注解的Redis缓存数据统一设置"有效期"为 1分钟,单位为"毫秒" spring.cache.redis.time-to-live= 60000
上述代码中,在 Spring Boot 全局配置文件 中添加了"spring.cache.redis.time-to-live "属性统一配置 Redis 数据的有效期
( 单位为毫秒 ),** 这种方式相对来说不够灵活** ,并且 这种设置方式中将 "基于 APl的 Redis 缓存" 实现** 没有效果**。
⑥ 基于注解的 "Redis查询" "缓存测试"
- 通过前面的操作 ,我们已经在项目中实现好了 关于 Redis 缓存管理 的 "配置 " 和 "操作代码 " , 并且在 项目启动类中 使用了 @EnableCaching开启了基于注解 "缓存管理 " , 下面可进行 "Redis的缓存管理 " 测试 ,访问controller类 中的指定url 进行 "缓存测试"。
三、基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理"
- 在 SpringBoot 整合 Redis 缓存实现中,除了** 基于注解形式的 Redis 缓存实现外,还有一个 开发中常用的方式** --- 基于 "API" 的 "Redis缓存实现" ,下面将通过 Redis API 的方式讲解 SpringBoot 整合 Redis缓存 的具体实现。
31. "RedisTemplate类"的 功能介绍 ( 通过该类可以在Java中 "操作Redis数据库 " )
- ① RedisTemplate类 ( Redis模板类 )是 Spring 框架提供的用于** 与 Redis 数据库进行交互的 工具类** ( 通过 该类 可以在 Java 中 "操作Redis数据库 " ) 。
- ② RedisTemplate 类 中 Spring Data Redis 提供的 直接进行Redis操作的** Java API** ( 通过该类 来操作Redis数据库 ),可以直接注入使用 ,相比于Jedis 更加简便。
- ③ RedisTemplate 可以 操作 <Object,Object > "对象类型" 数据,而其子类 StringRedisTemplate则是专门针对** <String,String> "字符串类型"** 的数据进行操作。
- ④ RedisTemplate 类中提供了很多** 操作Redis数据库** 的 方法 , 可以进行数据缓存查询 、缓存更新 、缓存修改 、缓存删除 以及设置缓存有效期等。
3.2 基于 "API" ( RedisTemplate类 ) 的 "Redis缓存管理" - 案例演示 :
① 准备数据
先创建 了一个 数据库springbootdata,然后创建了两个表 t_article 和 t_comment ,并向表中插入数据。
其中评论表t_comment 的a_id 与文章表t_article 的主键id 相关联 ( t_article 的主键 作为t_comment表 的 "外键")。
② 创建项目 + 开启Mysql服务 + 开启Redis服务
项目 的 目录结构 为 :
③ 在配置"全局配置文件" 中 "配置信息"
在配置"全局配置文件 " : application.properties 中 "配置信息" :
application.properties :
properties# mysql服务信息 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent=true spring.datasource.username=root spring.datasource.password=root #使用JPA操作数据库时,在控制台上显示sql语句 spring.jpa.show-sql=true #Redis服务地址 spring.data.redis.host=127.0.0.1 #Redis服务器连接端口 spring.data.redis.port=6379 #Reids服务器连接密码(默认为空) spring.data.redis.password=123456
④ 编写 "数据库表" 对应的 "实体类" ( 要实现"序列化" )
编写 "数据库表 " 对应的 "实体类 " ( 要实现"序列化" ) :
Comment.java :
javaimport jakarta.persistence.*; import java.io.Serializable; //指定该实现类映射的数据库表 @Entity(name = "t_Comment") //设置ORM实体类, 并指定对应的表明 public class Comment implements Serializable { // implements Serializable : 进行序列化,存储数据进Redis数据库时需要 //表示数据库表中主键对应的属性 @Id @GeneratedValue(strategy= GenerationType.IDENTITY) //设置主键的生成策略 (主键自增) private Integer id; @Column(name = "content") //指定映射的表字段名 private String content; @Column(name = "author") private String author; @Column(name = "a_id") private Integer aId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Integer getaId() { return aId; } public void setaId(Integer aId) { this.aId = aId; } @Override public String toString() { return "Comment{" + "id=" + id + ", content='" + content + '\'' + ", author='" + author + '\'' + ", aId=" + aId + '}'; } }
⑤ 编写 "操作数据库" 的 Repository接口文件 ( 通过该接口中的方法来 操作"Mysql数据库" )
编写 "操作数据库 " 的 Repository接口文件 :
CommentRepository.java :
javaimport com.myh.chapter_17.domain.Comment; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; //Repository接口中为操作数据库的方法 /* 继承了JpaRepository接口,其中有操作数据库的curd方法,也用方法关键字的形式来操作数据库,或者使用@Query注解的方式来操作数据库 */ public interface CommentRepository extends JpaRepository<Comment,Integer> { }
⑥ 编写 "控制器层"的 controller 对象
编写 "控制器层 "的 controller 对象 :
ApiCommentController.java :
javaimport org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController // 将该类加入到IOC容器中 + 将方法的返回值转换为指定的类型 存储到响应体中 @RequestMapping("/api") public class ApiCommentController { //控制层操作类 @Autowired private ApiCommentService apiCommentService; /** * 查询数据 */ @GetMapping("/get/{id}") //传递的参数为: 路径变量 public Comment findById(@PathVariable("id") int comment_id) { Comment comment = apiCommentService.findById(comment_id); return comment; } /** * 更新数据 */ @GetMapping("/update/{id}/{author}") public Comment updateComment(@PathVariable("id") int comment_id,@PathVariable("author") String author) { Comment updateComment = apiCommentService.updateComment(comment_id, author); return updateComment; } /** * 删除数据 */ @GetMapping("/delete/{id}") public void deleteComment(@PathVariable("id") int comment_id) { apiCommentService.deleteComment(comment_id); } }
⑦ 编写 "业务操作层"的 service 对象
编写 "业务操作层 "的 service 对象 :
ApiCommentService.java :
javaimport org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import java.util.Optional; import java.util.concurrent.TimeUnit; @Service //加入到IOC容器中 public class ApiCommentService { //业务操作类 @Autowired private CommentRepository commentRepository; //该接口继承了JPA相关的接口,通过其中的方法可操作Mysql数据库 @Autowired private RedisTemplate redisTemplate; //通过该类可在Java中操作Redis数据库 /** 从Mysql数据库中查询到数据后,将该数据存储到缓存中 (存储到Redis数据库中 ) */ public Comment findById(int comment_id) { //从Redis数据库中获取"缓存数据" ValueOperations valueOperations = redisTemplate.opsForValue(); Object object = valueOperations.get(comment_id); if (object != null) {//如果在Redis数据库中查询数据则返回 return (Comment) object; } else { //Reids中(缓存中)没有,进行数据库查询 Optional<Comment> optional = commentRepository.findById(comment_id); //判断从数据库中是否查询到数据 if (optional.isPresent()) { //获得该数据 Comment comment = optional.get(); //将从Mysql数据库中的查询结果进行"缓存" ( 缓存到Redis数据库中 ) , 设置有效期为1天 //设置的为Redis中的字符串数据 valueOperations.set(comment_id, comment, 1, TimeUnit.DAYS); //有效期为1天 return comment; } else { return null; } } } /** 更新Mysql数据库中的数据后,也更新缓存中的数据 (即同时也更新Redis数据库中的数据) */ public Comment updateComment(int comment_id,String author) { Comment comment = findById(comment_id); comment.setAuthor(author); comment = commentRepository.save(comment); //更新Mysql数据库中数据后,同时也更新缓存中的数据 ( 即更新Redis中的数据 ) ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set(comment_id,comment); return comment; } /** * 删除Mysql数据库中数据后,也删除Redis中的缓存数据 */ public void deleteComment(int comment_id) { //commentRepository.deleteById(comment_id); System.out.println("Mysql数据库中对应的数据删除成功....."); //删除Mysql数据库中数据后,也删除Redis数据库中的"缓存数据" Boolean commentId = redisTemplate.delete(comment_id); if (commentId) { System.out.println("Redis数据库中对应的缓存数据-删除成功....."); } } }
⑧ 基于 API ( RedisTemplate类 ) 的 "缓存管理" 测试
- 基于 API ( RedisTemplate类 ) 的 "缓存管理" 测试 :
访问 controller类中的** url进行测试即可**。