SpringBoot缓存管理(一) 默认缓存管理
前言
Spring框架支持透明地向应用程序添加缓存对缓存进行管理,其管理缓存的核心是将缓存应用于操作数据的方法(包括增删查改等),从而减少操作数据的执行次数(主要是查询,直接从缓存中读取数据),同时不会对程序本身造成任何干扰。
SpringBoot继承了Spring框架的缓存管理功能,通过使用@EnableCaching注解开启基于注解的缓存支持,SpringBoot就可以启动缓存管理的自动化配置。
接下来针对SpringBoot支持的默认缓存管理进行讲解。
SpringBoot默认缓存管理
1、基础环境搭建
(1)准备数据
使用前面 SpringBoot数据访问(一) SpringBoot整合Mybatis 一文中创建的数据库springbootdata,该数据库中包含两张数据表:t_article和t_comment。
(2)创建项目,代码编写
1、在项目依赖中添加SQL模块的JPA依赖、MySql依赖以及Web模块中的Web依赖,如下图所示:

引入这三个依赖器创建项目,在项目pom.xml文件会出现以下依赖:

2、编写数据库表对应的实体类,并使用JPA相关注解配置映射关系
package com.hardy.springbootdatacache.entity; import org.springframework.data.annotation.Id; import javax.persistence.*; /**
* @Author: HardyYao
* @Date: 2021/6/19
*/
@Entity(name = "t_comment") // 设置ORM实体类,并指定映射的表名
public class Comment { @Id // 映射对应的主键id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 设置主键自增策略
private Integer id; private String content; 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 +
'}';
}
}
3、编写数据库操作的Repository接口文件
package com.hardy.springbootdatacache.repository; import com.hardy.springbootdatacache.entity.Comment;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional; /**
* @Author: HardyYao
* @Date: 2021/6/19
*/
public interface CommentRepository extends JpaRepository<Comment, Integer> { /**
* 根据评论id修改评论作者author
* @param author
* @param id
* @return
*/
@Transactional
@Modifying
@Query("update t_comment c set c.author = ?1 where c.id=?2")
int updateComment(String author,Integer id); }
4、编写service层
package com.hardy.springbootdatacache.service; import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.repository.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import java.util.Optional; /**
* @Author: HardyYao
* @Date: 2021/6/19
*/
@Service
public class CommentService { @Autowired
private CommentRepository commentRepository; /**
* 根据评论id查询评论
* @Cacheable:将该方法的查询结果comment存放在SpringBoot默认缓存中
* cacheNames:起一个缓存命名空间,对应缓存唯一标识
* @param id
* @return
*/
@Cacheable(cacheNames = "comment")
public Comment findCommentById(Integer id){
Optional<Comment> comment = commentRepository.findById(id);
if(comment.isPresent()){
Comment comment1 = comment.get();
return comment1;
}
return null;
} }
5、编写controller层
package com.hardy.springbootdatacache.controller; import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @Author: HardyYao
* @Date: 2021/6/19
*/
@RestController
public class CommentController { @Autowired
private CommentService commentService; @RequestMapping(value = "/findCommentById")
public Comment findCommentById(Integer id){
Comment comment = commentService.findCommentById(id);
return comment;
} }
6、编写配置文件
在全局配置文件application.properties中编写对应的数据库连接配置
# MySQL数据库连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
# 显示使用JPA进行数据库查询的SQL语句
spring.jpa.show-sql=true # 开启驼峰命名匹配映射
mybatis.configuration.map-underscore-to-camel-case=true
# 解决中文乱码问题
spring.http.encoding.force-response=true
7、测试
在浏览器中输入:http://localhost:8080/findCommentById?id=1 进行访问(连续访问三次):


在上图中,因为没有在SpringBoot项目中开启缓存管理,故虽然数据表中的数据没有任何变化,但是每执行一次查询操作,即便执行的是相同的SQL语句,都还是会访问一次数据库。
2、默认缓存使用
在前面搭建的Web应用的基础上,开启SpringBoot默认支持的缓存,以使用SpringBoot默认缓存。
1、在项目启动类的类名上方使用@EnableCaching注解开启基于注解的缓存支持
package com.hardy.springbootdatacache; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching; @EnableCaching // 开启SpringBoot基于注解的缓存管理支持
@SpringBootApplication
public class SpringbootdataCacheApplication { public static void main(String[] args) {
SpringApplication.run(SpringbootdataCacheApplication.class, args);
} }
2、使用@Cacheable注解对数据操作方法进行缓存管理
将@Cacheable注解标注在Service类的查询方法上,对查询结果进行缓存:
package com.hardy.springbootdatacache.service; import com.hardy.springbootdatacache.entity.Comment;
import com.hardy.springbootdatacache.repository.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import java.util.Optional; /**
* @Author: HardyYao
* @Date: 2021/6/19
*/
@Service
public class CommentService { @Autowired
private CommentRepository commentRepository; /**
* 根据评论id查询评论
* @param id
* @return
*/
@Cacheable(cacheNames = "comment")
public Comment findCommentById(Integer id){
Optional<Comment> comment = commentRepository.findById(id);
if(comment.isPresent()){
Comment comment1 = comment.get();
return comment1;
}
return null;
} }
3、测试访问
在浏览器中输入:http://localhost:8080/findCommentById?id=1 进行访问(连续访问三次):


可以看到,在使用SpringBoot默认缓存注解后,重复进行同样的查询操作,数据库只执行了一次SQL查询语句,说明项目开启的默认缓存支持已生效。
SpringBoot默认缓存底层结构:在诸多的缓存自动配置类中,SpringBoot默认装配的是SimpleCacheConfiguration,它使用的CacheManager是ConcurrentMapCacheManager,使用ConcurrentMap作为底层的数据结构,根据Cache的名字查询出Cache,每一个Cache中存在多个key-value键值对、缓存值。
4、缓存注解介绍
前面我们通过使用@EnableCaching、@Cacheable注解实现了SpringBoot默认的基于注解的缓存管理,除此之外,还有其它注解及注解属性也可用于配置优化缓存管理。下面,我们对@EnableCaching、@Cacheable及其他与缓存管理相关的注解进行介绍。
4.1、@EnableCaching注解
@EnableCaching注解是由Spring框架提供的,SpringBoot框架对该注解进行了继承,该注解需要配置在类的上方(一般配置在项目启动类上),用于开启基于注解的缓存支持。
4.2、@Cacheable注解
@Cacheable注解也是由Spring框架提供的,可以作用于类或方法上(通常作用于数据查询方法上),用于对方法的执行结果进行数据缓存存储。注解的执行顺序是:先进行缓存查询,如果为空则进行方法查询(查数据库),并将结果进行缓存;如果缓存中有数据,则不进行方法查询,而是直接使用缓存数据。
@Cacheable注解提供了多个属性,用于对缓存存储进行相关设置,如下所示:

执行流程&时机
方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取,(CacheManager先获取相应的缓存),第一次获取缓存如果获取不到,Cache组件会自动创建。
去Cache中查找缓存的内容,使用一个key进行查找,默认在只有一个参数的情况下,key值默认就是方法的参数;如果有多个参数或者没有参数,则SpringBoot会按照某种策略生成key,默认是使用KeyGenerator生成的,其实现类为SimpleKeyGenerator。
SimpleKeyGenerator生成key的默认策略:

常用的SPEL表达式:

4.3、@CachePut注解
目标方法执行完之后生效。@CachePut被使用于修改操作较多,若缓存中已经存在目标值了,该注解作用的方法依然会执行,执行后将结果保存在缓存中(覆盖掉原来的目标值)。
@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。
4.4、@CacheEvict注解
@CacheEvict注解也是由Spring框架提供的,可以作用于类或方法上(通常作用于数据删除方法上),该注解的作用是删除缓存数据。
@CacheEvict注解的默认执行顺序是:先进行方法调用,然后将缓存进行清除。
SpringBoot缓存管理(一) 默认缓存管理的更多相关文章
- 【缓存】.net中Cache管理操作
隐藏行号 复制代码 ? 这是一段程序代码. using System; using System.Web; using System.Web.Caching; using System.Collect ...
- Redis-基本概念、java操作redis、springboot整合redis,分布式缓存,分布式session管理等
NoSQL的引言 Redis数据库相关指令 Redis持久化相关机制 SpringBoot操作Redis Redis分布式缓存实现 Resis中主从复制架构和哨兵机制 Redis集群搭建 Redis实 ...
- QCache 缓存(类似于map的模板类,逻辑意义上的缓存Cache,方便管理,默认类似于LRU的淘汰算法)
最近在学习缓存方面的知识,了解了缓存(Cache)的基本概念,为什么要使用缓存,以及一些缓存算法(缓存替换),如LRU.LFU.ARC等等. 这些缓存算法的实现过程会使用一些基本的数据结构,如list ...
- ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存
ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存 hibernate : Hibernate是一个持久层框架,经常访问物理数据库 ...
- 攻城狮在路上(壹) Hibernate(十八)--- 管理Hibernate的缓存
一般Session的缓存被称为Hibernate的第一级缓存,SessionFactory的外置缓存是一个可配置的缓存插件,称为Hibernate的第二级缓存.一.缓存的基本原理: 1.持久化层的缓存 ...
- Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
介绍总结的一些android公共库,包含缓存(图片缓存.预取缓存).公共View(下拉及底部加载更多ListView.底部加载更多ScrollView.滑动一页Gallery).及Android常用工 ...
- Springboot Mybatis Redis 实现二级缓存
前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...
- springboot集成shiro实现权限缓存和记住我
到这节为止,我们已经实现了身份验证和权限验证.但是,如果我们登录之后多次访问http://localhost:8080/userInfo/userDel的话,会发现权限验证会每次都执行一次.这是有问题 ...
- (十五)SpringBoot之使用Redis做缓存数据
一.添加Redis依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
随机推荐
- 利用rsync备份生产应用(二)
概述 上节主要是针对rsync服务端进行的配置和详解,本节主要针对在客户端上的rsync配置进行讲解. rsync用法 本地到本地 语法:rsync [OPTION...] SRC... [DEST] ...
- gpcj-07.为什么是连锁零售类公司
1.量化分析的真面目 本课的目的: ·理解零售类公司价值分析的逻辑·学会量化分析公司的思路和原理前言的前沿 和大部分投资者不同,我们的投资核心之一,就是从下而上的分析.宏观经济对我们公司分析影响极少. ...
- 校准仪的开发 ---等下整理 迪文屏的ICO文件 和输出配置问题
要有ICO文件才能
- 矩阵中的路径 DFS+剪枝
给定一个 m x n 二维字符网格 board 和一个字符串单词 word .如果 word 存在于网格中,返回 true :否则,返回 false . 单词必须按照字母顺序,通过相邻的单元格内的字母 ...
- clickhouse_各个引擎表的特点
去重表:RepalcingMergeTree 1.使用order by排序键作为判断重复数据的唯一键 2.只有在合并分区的时候才会触发删除重复数据的逻辑 3.以数据分区为单位删除重复数据.当分区合并时 ...
- Python小白的数学建模课-04.整数规划
整数规划与线性规划的差别只是变量的整数约束. 问题区别一点点,难度相差千万里. 选择简单通用的编程方案,让求解器去处理吧. 『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛达 ...
- 再见Xshell、Xftp!Python执行Linux命令、上传下载远程文件
相信大家应该都接触过Linux操作系统(Ubuntu.Centos等),那么在使用的Linux操作系统需要使用一些远程ssh工具,尤其是公网服务器. 常用的ssh工具主要有:Xshell.MobaXt ...
- 先进一站式IP及定制
先进一站式IP及定制 芯动科技15年来立足中国本土,目前已实现从130nm到5nm工艺高速混合电路IP核全覆盖,且所有IP均自主可控,一站式赋能国产芯片发展. 提供经过批量生产验证或硅验证的IP产品, ...
- HiCar人-车-家全场景智慧互联
HiCar人-车-家全场景智慧互联 (HUAWEI HiCar Smart Connection)解决方案,具备如下特点: 安全交互:以安全为前提的极简交互(Safety) 无感互联:手机/IoT 设 ...
- 所有处理都走向AI
所有处理都走向AI All Processing Bends Toward AI 旧金山--谷歌正在试验机器学习(ML)来执行集成电路设计中的位置和路径,并取得了很好的效果.上周在ISSCC会议上宣布 ...