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=" ...
随机推荐
- Linux软件安装管理之——dpkg与apt-*详解
Linux软件安装管理之--dpkg与apt-*详解 [Linux软件安装管理系列]- - 传送门: - -<Linux软件安装管理之--源码安装详解> - -<Linux软件安装管 ...
- robot framework列表
一.列表(list) python中创建列表:a=[1,2,3],b=[],c=[a,b,c,[1,2,3]],d=[a,b,c,1,2,3] robotframework中创建列表(list):通过 ...
- mysql基础之mysql双主(主主)架构
一.概念 在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果是双主或者多主,就会增加m ...
- visual studio code 快捷键-(转自 浅笑千寻)
Visual Studio Code之常备快捷键 官方快捷键大全:https://code.visualstudio.com/docs/customization/keybindings Visual ...
- Java求余%引发的一连串故事
C1 RCE对%的处理 HotSpot VM的C1有个RCE(Range Check Elimination,范围检查消除)优化,所谓范围检查消除,就是为了正确的抛出数组越界异常,虚拟机需要在数组访问 ...
- 只需5分钟!一文读懂CSS布局(二) -- flex布局
目录 简介 基本概念 容器属性 1. flex-direction 测试代码 2. flex-wrap 3. flex-flow 4. justify-content 5. align-items 6 ...
- 记go中一次http超时引发的事故
记一次http超时引发的事故 前言 分析下具体的代码实现 服务设置超时 客户端设置超时 http.client context http.Transport 问题 总结 参考 记一次http超时引发的 ...
- Eclipse从SVN中检出项目缺少Jar包的问题
Eclipse从SVN中检出项目缺少Jar包的问题
- npm ERR! Error: tunneling socket could not be established的解决问题
一般是代理问题 可以通过在命令行运行下列命令解决: npm run server npm run webdriver-update
- CUDA上的量化深度学习模型的自动化优化
CUDA上的量化深度学习模型的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参 ...