SpringBoot系列之缓存使用教程

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介:

SpringBoot系列之缓存使用教程

介绍SpringBoot项目中使用缓存,之前先介绍一下Spring的缓存抽象和JSR107,本博客是我在学习尚硅谷视频和参考其它博客之后做的笔记,仅供学习参考

@

目录
一、Spring的缓存抽象
1.1、缓存抽象定义
1.2、重要接口
二、JSR107
2.1、JSR107核心接口
2.2、JSR107图示
三、Spring缓存使用
3.1、重要注解简介
3.2、环境准备
3.3、引入spring-boot-starter-cache模块
3.4、主要注解例子实践
3.4.1、@EnableCaching
3.4.2、@Cacheable注解
3.4.3、@CachePut注解
3.4.4、 @CacheEvic注解
3.4.5、@Caching注解
3.4.6、 @CacheConfig注解
四、集成Redis缓存
4.1、环境准备
4.2、Redis配置类实现
4.3、RestTemplate相关操作
4.4、缓存业务测试
一、Spring的缓存抽象
1.1、缓存抽象定义
Spring从3.1开始定义了org.springframework.cache.Cache
和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用Java Caching(JSR-107)注解简化我们进行缓存开发。Spring Cache 只负责维护抽象层,具体的实现由你的技术选型来决定。将缓存处理和缓存技术解除耦合。

1.2、重要接口
Cache:缓存抽象的规范接口,缓存实现有:RedisCache、EhCacheCache、ConcurrentMapCache等
CacheManager:缓存管理器,管理Cache的生命周期
二、JSR107
2.1、JSR107核心接口
Java Caching(JSR-107)定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry和 Expiry。

CachingProvider:创建、配置、获取、管理和控制多个CacheManager
CacheManager:创建、配置、获取、管理和控制多个唯一命名的Cache,Cache存在于CacheManager的上下文中。一个CacheManager仅对应一个CachingProvider
Cache:是由CacheManager管理的,CacheManager管理Cache的生命周期,Cache存在于CacheManager的上下文中,是一个类似map的数据结构,并临时存储以key为索引的值。一个Cache仅被一个CacheManager所拥有
Entry:是一个存储在Cache中的key-value对
Expiry:每一个存储在Cache中的条目都有一个定义的有效期。一旦超过这个时间,条目就自动过期,过期后,条目将不可以访问、更新和删除操作。缓存有效期可以通过ExpiryPolicy设置
2.2、JSR107图示
引用尚硅谷视频课件中的图示:

三、Spring缓存使用
3.1、重要注解简介
例子实践之前,先简单介绍Spring提供的重要缓存注解

@Cacheable:针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict:清空缓存
@CachePut:既调用方法,又更新缓存数据
@EnableCaching:开启基于注解的缓存
@Caching:定义复杂的缓存规则
3.2、环境准备
ok,本博客以尚硅谷视频例子进行改写,用这个比较经典的例子进行说明

环境准备:

maven环境
IntelliJ IDEA
新建两张表:
DROP TABLE IF EXISTS employee;
CREATE TABLE employee (
id int(11) NOT NULL AUTO_INCREMENT,
lastName varchar(255) DEFAULT NULL,
email varchar(255) DEFAULT NULL,
gender int(2) DEFAULT NULL,
d_id int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS department;
CREATE TABLE department (
id int(11) NOT NULL AUTO_INCREMENT,
departmentName varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.3、引入spring-boot-starter-cache模块

        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>

3.4、主要注解例子实践
3.4.1、@EnableCaching
@EnableCaching开启基于注解的缓存

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class SpringbootCacheApplication {

public static void main(String[] args) {
    SpringApplication.run(SpringbootCacheApplication.class, args);
}

}

3.4.2、@Cacheable注解
@Cacheable注解的作用,前面也简介了,主要是针对方法配置,能够根据方法的请求参数对其结果进行缓存,介绍一下注解的主要属性

cacheNames/value:指定缓存组件的名字,数组形式
key:缓存数据使用的key,确定缓存可以用唯一key进行指定;eg:编写SpEL; #id,参数id的值 ,,#a0(第一个参数), #p0(和a0的一样的意义) ,#root.args[0]
keyGenerator:key的生成器;可以自己指定key的生成器的组件id(注意: key/keyGenerator:二选一使用;不能同时使用)
cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器
condition:指定符合条件的情况下才缓存;使用SpEl表达式,eg:condition = "#a0>1":第一个参数的值>1的时候才进行缓存
unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;eg:unless = "#a0!=2":如果第一个参数的值不是2,结果不缓存;
sync:是否使用异步模式

@Cacheable(value = {"emp"}, /*keyGenerator = "myKeyGenerator",*/key = "#id",condition = "#a0>=1",unless = "#a0!=2")
public Employee getEmp(Integer id) {
    Employee employee = this.employeeMapper.getEmpById(id);
    LOG.info("查询{}号员工数据",id);
    return employee;
}

这里也可以使用自定义的keyGenerator,使用属性keyGenerator = "myKeyGenerator

定义一个@Bean类,将KeyGenerator添加到Spring容器

@Configuration
public class CacheConfig {

@Bean(value = {"myKeyGenerator"})
public KeyGenerator keyGenerator(){
    return new KeyGenerator() {
        @Override
        public Object generate(Object target, Method method, Object... params) {
            return method.getName()+"["+ Arrays.asList(params).toString()+"]";
        }
    };
}

}
3.4.3、@CachePut注解
@CachePut注解也是一个用来缓存的注解,不过缓存和@Cacheable有明显的区别是即调用方法,又更新缓存数据,也就是执行方法操作之后再来同步更新缓存,所以这个主键常用于更新操作,也可以用于查询,主键属性和@Cacheable有很多类似的,详情参看@link @CachePut源码

/**

 *  @CachePut:既调用方法,又更新缓存数据;同步更新缓存
 *  修改了数据,同时更新缓存
 */
@CachePut(value = {"emp"}, key = "#result.id")
public Employee updateEmp(Employee employee){
    employeeMapper.updateEmp(employee);
    LOG.info("更新{}号员工数据",employee.getId());
    return employee;
}

3.4.4、 @CacheEvic注解
主要属性:

key:指定要清除的数据
allEntries = true:指定清除这个缓存中所有的数据
beforeInvocation = false:默认代表缓存清除操作是在方法执行之后执行
beforeInvocation = true:代表清除缓存操作是在方法运行之前执行

@CacheEvict(value = {"emp"}, beforeInvocation = true,key="#id")
public void deleteEmp(Integer id){
    employeeMapper.deleteEmpById(id);
    //int i = 10/0;
}

3.4.5、@Caching注解
@Caching 用于定义复杂的缓存规则,可以集成@Cacheable和 @CachePut

// @Caching 定义复杂的缓存规则

@Caching(
        cacheable = {
                @Cacheable(/*value={"emp"},*/key = "#lastName")
        },
        put = {
                @CachePut(/*value={"emp"},*/key = "#result.id"),
                @CachePut(/*value={"emp"},*/key = "#result.email")
        }
)
public Employee getEmpByLastName(String lastName){
    return employeeMapper.getEmpByLastName(lastName);
}

3.4.6、 @CacheConfig注解
@CacheConfig注解可以用于抽取缓存的公共配置,然后在类加上就可以,eg:@CacheConfig(cacheNames = {"emp"},cacheManager = "employeeCacheManager")

附录拓展:SpEL表达式用法

Cache SpEL available metadata

名称 位置 描述 示例
methodName root对象 当前被调用的方法名 #root.methodname
method root对象 当前被调用的方法 #root.method.name
target root对象 当前被调用的目标对象实例 #root.target
targetClass root对象 当前被调用的目标对象的类 #root.targetClass
args root对象 当前被调用的方法的参数列表 #root.args[0]
caches root对象 当前方法调用使用的缓存列表 #root.caches[0].name
argument Name 执行上下文(avaluation context) 当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数 #artsian.id
result 执行上下文(evaluation context) 方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false) #result
四、集成Redis缓存
4.1、环境准备
基于前面的Spring缓存环境,集成redis要引入相关配置:

        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
    </dependency>

切换缓存方式为Redis:spring.cache.type=redis

4.2、Redis配置类实现
RedisTemplate配置

@Resource

private LettuceConnectionFactory lettuceConnectionFactory;

@Bean
@Primary
public RedisTemplate<Object,Object> redisTemplate(){
    RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<Object, Object>();
    redisTemplate.setConnectionFactory(lettuceConnectionFactory);
    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = this.initJacksonSerializer();
    // 设置value的序列化规则和 key的序列化规则
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.afterPropertiesSet();
    return redisTemplate;
}

RedisCacheManager相关代码可以参考博文,该博主已经对代码做了比较好的封装,所以本文不复制代码

4.3、RestTemplate相关操作
使用RestTemplate操作redis

1、 redisTemplate.opsForValue();//操作字符串
2、redisTemplate.opsForHash();//操作hash
3、redisTemplate.opsForList();//操作list
4、redisTemplate.opsForSet();//操作set
5、redisTemplate.opsForZSet();//操作有序set
4.4、缓存业务测试
@Autowired

DepartmentMapper departmentMapper;

@Qualifier("redisCacheManager")
@Autowired
RedisCacheManager redisCacheManager;

// @Cacheable(cacheNames = "dept",cacheManager = "redisCacheManager")
// public Department getDeptById(Integer id){
// System.out.println("查询部门"+id);
// Department department = departmentMapper.getDeptById(id);
// return department;
// }

// 使用缓存管理器得到缓存,进行api调用

public Department getDeptById(Integer id){

    LOG.info("查询id为{}的员工信息",id);

    //获取某个缓存
    Cache deptCache = redisCacheManager.getCache("dept");
    Department department = null;
    if(deptCache.get(id)==null){
        department = departmentMapper.getDeptById(id);
        deptCache.put(id,department);
    } else {
        SimpleValueWrapper valueWrapper = (SimpleValueWrapper) deptCache.get(id);
        department = (Department)valueWrapper.get();
    }

    return department;
}

当然使用前面的Spring主键也是可以缓存的,

参考博文:
缓存抽象层Spring cache实战操作

代码例子下载:github链接

原文地址https://www.cnblogs.com/mzq123/p/12629142.html

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
24天前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
35 0
|
2月前
|
Cloud Native Java C++
Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)
文章介绍如何在Spring Boot 3中利用GraalVM将Java应用程序编译成独立的本机二进制文件,从而提高启动速度、减少内存占用,并实现不依赖JVM运行。
304 1
Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)
|
2月前
|
前端开发 Java 数据安全/隐私保护
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
文章通过一个简单的SpringBoot项目,详细介绍了前后端如何实现用户登录功能,包括前端登录页面的创建、后端登录逻辑的处理、使用session验证用户身份以及获取已登录用户信息的方法。
375 2
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
|
4月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
110 1
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
2月前
|
Java API Apache
Springboot+shiro,完整教程,带你学会shiro
这篇文章提供了一个完整的Apache Shiro与Spring Boot结合使用的教程,包括Shiro的配置、使用以及在非Web和Web环境中进行身份验证和授权的示例。
101 2
Springboot+shiro,完整教程,带你学会shiro
|
2月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
522 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
2月前
|
缓存 NoSQL Java
springboot的缓存和redis缓存,入门级别教程
本文介绍了Spring Boot中的缓存机制,包括使用默认的JVM缓存和集成Redis缓存,以及如何配置和使用缓存来提高应用程序性能。
128 1
springboot的缓存和redis缓存,入门级别教程
|
3月前
|
JavaScript Java 关系型数据库
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
本文介绍了一个基于Spring Boot和Vue.js实现的在线考试系统。随着在线教育的发展,在线考试系统的重要性日益凸显。该系统不仅能提高教学效率,减轻教师负担,还为学生提供了灵活便捷的考试方式。技术栈包括Spring Boot、Vue.js、Element-UI等,支持多种角色登录,具备考试管理、题库管理、成绩查询等功能。系统采用前后端分离架构,具备高性能和扩展性,未来可进一步优化并引入AI技术提升智能化水平。
毕设项目&课程设计&毕设项目:基于springboot+vue实现的在线考试系统(含教程&源码&数据库数据)
|
3月前
|
Java 关系型数据库 MySQL
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和JSP技术的房屋租赁系统,旨在通过自动化和信息化手段提升房屋管理效率,优化租户体验。系统采用JDK 1.8、Maven 3.6、MySQL 8.0、JSP、Layui和Spring Boot 2.0等技术栈,实现了高效的房源管理和便捷的租户服务。通过该系统,房东可以轻松管理房源,租户可以快速找到合适的住所,双方都能享受数字化带来的便利。未来,系统将持续优化升级,提供更多完善的服务。
毕设项目&课程设计&毕设项目:springboot+jsp实现的房屋租租赁系统(含教程&源码&数据库数据)