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注解的默认执行顺序是:先进行方法调用,然后将缓存进行清除。
最新文章
- 【001:转载 ubuntu下: 建立本地SVN服务器】
- Python: Catch multiple exceptions in one line (except block)
- BZOJ 1455
- Windows Phone 8初学者开发—第17部分:Coding4Fun工具包简介
- java封装的方法
- 在VB6/VBA中使用正则表达式
- .NET垃圾回收机制 GC
- sql注入中关于--+的一点探索
- Chapter 5 Blood Type——10
- tensorflow中batch normalization的用法
- 自动化测试 | UI Automator 入门指南
- HDU 6315 Naive Operations(线段树区间整除区间)
- [leetcode]210. Course Schedule II课程表II
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #21FUSE
- Windows注意目录
- SOAP与REST比较(转)
- mongoDB操作2
- [转]关于sdk更新Android SDK Tools 25.3.1版本后使用sdk manager闪退
- c++ 反射类型
- [洛谷P4168][Violet]蒲公英
热门文章
- Spring Cloud Alibaba Nacos Discovery 实战
- linux系统瓶颈分析(精) CPU Memory IO Network
- Keil编译后的Code,RO,RW,ZI分别表示什么以及和芯片Flash、SRAM的对应关系
- 删除win10系统下文件默认打开方式的关联-win10配置
- 大数据学习之路—环境配置——IP设置(虚拟机修改Ip的内在原因及实现)
- MongoDB学习笔记:文档Crud Shell
- Manjaro Linux安装singularity-container
- 五、SVM推导过程
- Asp.Net Core Api 使用Swagger管理文档教程的安装与使用
- 关于MongoDB ObjectId的那些事儿