前言

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缓存管理(一) 默认缓存管理的更多相关文章

  1. 【缓存】.net中Cache管理操作

    隐藏行号 复制代码 ? 这是一段程序代码. using System; using System.Web; using System.Web.Caching; using System.Collect ...

  2. Redis-基本概念、java操作redis、springboot整合redis,分布式缓存,分布式session管理等

    NoSQL的引言 Redis数据库相关指令 Redis持久化相关机制 SpringBoot操作Redis Redis分布式缓存实现 Resis中主从复制架构和哨兵机制 Redis集群搭建 Redis实 ...

  3. QCache 缓存(类似于map的模板类,逻辑意义上的缓存Cache,方便管理,默认类似于LRU的淘汰算法)

    最近在学习缓存方面的知识,了解了缓存(Cache)的基本概念,为什么要使用缓存,以及一些缓存算法(缓存替换),如LRU.LFU.ARC等等. 这些缓存算法的实现过程会使用一些基本的数据结构,如list ...

  4. ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存

    ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存 hibernate  : Hibernate是一个持久层框架,经常访问物理数据库 ...

  5. 攻城狮在路上(壹) Hibernate(十八)--- 管理Hibernate的缓存

    一般Session的缓存被称为Hibernate的第一级缓存,SessionFactory的外置缓存是一个可配置的缓存插件,称为Hibernate的第二级缓存.一.缓存的基本原理: 1.持久化层的缓存 ...

  6. Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)

    介绍总结的一些android公共库,包含缓存(图片缓存.预取缓存).公共View(下拉及底部加载更多ListView.底部加载更多ScrollView.滑动一页Gallery).及Android常用工 ...

  7. Springboot Mybatis Redis 实现二级缓存

    前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...

  8. springboot集成shiro实现权限缓存和记住我

    到这节为止,我们已经实现了身份验证和权限验证.但是,如果我们登录之后多次访问http://localhost:8080/userInfo/userDel的话,会发现权限验证会每次都执行一次.这是有问题 ...

  9. (十五)SpringBoot之使用Redis做缓存数据

    一.添加Redis依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

随机推荐

  1. [DB] mysql windows 安装

    参考 mysql安装 https://www.cnblogs.com/zhangkanghui/p/9613844.html navicat for mysql 中文破解版(无需激活码) https: ...

  2. 磁盘IO过高时的处理办法 针对系统中磁盘IO负载过高的指导性操作

    磁盘IO过高时的处理办法 针对系统中磁盘IO负载过高的指导性操作 主要命令:echo deadline > /sys/block/sda/queue/scheduler 注:以下的内容仅是提供参 ...

  3. Mysql 数据库基本操作

    1.数据库设置密码 [root@db02 scripts]# mysqladmin -uroot password 123 2.使用密码登录 #1.正确的方式(不规范) [root@db02 scri ...

  4. 云计算OpenStack---虚拟机获取不到ip(12)

    一.现象描述 openstack平台中创建虚拟机后,虚拟机在web页面中显示获取到了ip,但是打开虚拟机控制台后查看网络状态,虚拟机没有ip地址,下图为故障截图: 二.分析 1.查看neutron服务 ...

  5. 11.11 ntsysv:管理开机服务

    ntsysv命令提供了一种基于文本界面的菜单操作方式,以设置不同运行级别下的系统服务启动状态.   -back    在交互界面里,显示Back按钮,而非Cancel按钮 -level    指定运行 ...

  6. 3D网页小实验-基于Babylon.js与recast.js实现RTS式单位控制

    一.运行效果 1.建立一幅具有地形起伏和不同地貌纹理的地图: 地图中间为凹陷的河道,两角为突出的高地,高地和低地之间以斜坡通道相连. 水下为沙土材质,沙土材质网格贴合地形,河流材质网格则保持水平. 2 ...

  7. GO学习-(29) Go语言操作etcd

    Go语言操作etcd etcd是近几年比较火热的一个开源的.分布式的键值对数据存储系统,提供共享配置.服务的注册和发现,本文主要介绍etcd的安装和使用. etcd etcd介绍 etcd是使用Go语 ...

  8. MLPerf Inference 0.7应用

    MLPerf Inference 0.7应用 三个趋势继续推动着人工智能推理市场的训练和推理:不断增长的数据集,日益复杂和多样化的网络,以及实时人工智能服务. MLPerf 推断 0 . 7 是行业标 ...

  9. 英特尔Intel® Arria® 10 FPGA加速器设计

    英特尔Intel Arria 10 FPGA加速器设计 Introducing the Intel Vision Accelerator Design with Intel Arria 10 FPGA ...

  10. 35 张图带你 MySQL 调优

    这是 MySQL 基础系列的第四篇文章,之前的三篇文章见如下链接 138 张图带你 MySQL 入门 47 张图带你 MySQL 进阶!!! 炸裂!MySQL 82 张图带你飞 一般传统互联网公司很少 ...