SpringBoot学习笔记-9:第九章 Spring Boot 与缓存

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: SpringBoot学习笔记-9:第九章 Spring Boot 与缓存

第九章 Spring Boot 与缓存

主要内容

JSR-107
Spring 缓存抽象
整合 Redis

1、JSR-107

Java Caching 定义了 5 个核心接口

CachingProvider:管理多个CacheManager
CacheManager:管理多个Cache
Cache:类似Map数据结构
Entry:存储在Cache中的key-value对
Expiry: 有效期
Application
    - CachingProvider
        - CacheManager
            - Cache
                Entry <-> Expiry

Spring 缓存抽象简介

重要概念

Cache 缓存接口,实现 RedisCache、EhCacheCache、ConcurrentMapCache
CacheManager 缓存管理器
@Cacheable 根据方法请求参数,对结果进行缓存
@CacheEvict 清空缓存
@CachePut 保证方法被调用,又希望结果被缓存
@EnableCaching 开启基于注解的缓存
keyGenerator 缓存数据时 key 的生成策略
serialize 缓存数据时 value 序列化策略

1、搭建环境

引入 Spring 依赖

Cache
Web
MySQL
MyBatis
  • 导入数据库文件,创建出 employee 和 department 表
  • 创建 javabean 封装数据
  • 整合 MyBatis 操作数据库
  • 配置数据源信息
  • 使用注解版 MyBatis
  • @MapperScan 指定需要扫描的 Mapper 接口所在包

2、使用缓存

  • 开启基于注解的缓存 @EnableCaching
  • 标注缓存注解 @Cacheable

@Cacheable

SpEL

methodName 方法名
method 方法
target 目标对象
targetClass 目标对象类
args 参数列表
caches 缓存列表
argumentname 参数名
result 返回值

参数

value 缓存组件名
key 缓存使用的key, 默认使用方法参数值
keyGenerator 指定key的生成器,和key二选一
cacheManager 缓存管理器
cacheResolver 缓存解析器 和缓存管理器二选一
condition 缓存条件 eg: #id>0
unless 否定缓存 条件为true不缓存
sync 使用同步

缓存工作原理

自动配置类

CacheAutoConfiguration

GenericCacheConfiguration"
JCacheCacheConfiguration"
EhCacheCacheConfiguration"
HazelcastCacheConfiguration"
InfinispanCacheConfiguration"
CouchbaseCacheConfiguration"
RedisCacheConfiguration"
CaffeineCacheConfiguration"
SimpleCacheConfiguration"
NoOpCacheConfiguration"

默认使用 SimpleCacheConfiguration

cacheManager:ConcurrentMapCacheManager

运行流程:

  1. 执行方法之前,先按照 cacheNames 获取 Cache 缓存组件,暗
    第一次获取缓存如果没有 cache 组件就创建
  2. 按照某种策略生成 key,查抄内容
  1. 没有查找到缓存就调用目标方法
  2. 目标方法换回的结果放进缓存中

SimpleKeyGenerator 默认策略

  • 如果没有参数 key = new SimpleKey()
  • 如果有一个参数 key = 参数值
  • 如果有多个参数 key - new SimpleKey(params)

核心:

  • 获取 CacheManger(默认 ConcurrentMapCacheManager)
  • 使用 KeyGenerator 生成 key 默认 SimpleKeyGenerator

自定义 key 的生成方式

package com.example.demo.config;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.util.Arrays;
@Configuration
public class MyCacheConfig {
    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(){
        return new KeyGenerator(){
            @Override
            public Object generate(Object target, Method method, Object... params) {
                System.out.println("generate");
                return method.getName() + "[" + Arrays.asList(params).toString()+ "]";
            }
        };
    }
}
// keyGenerator和key二选一
// key 支持SpEL表达式
@Cacheable(value = "department", key = "#id")
public Department getById(Integer id){
    return departmentMapper.getById(id);
}
// keyGenerator
@Cacheable(value = "department", keyGenerator = "myKeyGenerator")
public Department getById(Integer id){
    return departmentMapper.getById(id);
}

@CachePut

@CachePut 既调用方法,又更新缓存数据

修改了数据库的某个数据,同时更新缓存

运行时机:先调用目标方法,再将方法的结果缓存

@CachePut(value = "department", key="#department.id")
public Department update(Department department){
    departmentMapper.update(department);
    return department;
}

@CacheEvict

@CacheEvict 缓存删除

参数

key 清除指定缓存
allEntries  清除所有缓存
beforeInvocation 清除缓存在方法运行之前执行 默认false=方法之后执行
// 清除单个缓存
@CacheEvict(value = "department", key="#id")
public String  delete(Integer id){
    return "success";
}
// 清除所有缓存
@CacheEvict(value = "department", allEntries = true)
    public String  deleteAllCache(){
        return "success";
    }

@Caching&@CacheConfig

public @interface Caching {
  Cacheable[] cacheable() default {};
  CachePut[] put() default {};
  CacheEvict[] evict() default {};
}

CacheConfig 抽取缓存公共配置

@CacheConfig(cacheNames={"department"})
@Service
public class DepartmentService {
    @Autowired
    private DepartmentMapper departmentMapper;
    // 缓存数据
    @Cacheable(key = "#id")
    public Department getById(Integer id){
        return departmentMapper.getById(id);
    }
}

搭建 redis 环境&测试

本机安装

# 启动
$ redis-server
# 停止本机redis
$ redid-cli shutdown

可以使用 Docker 方式安装

https://hub.docker.com/

# 安装
docker pull redis
# 启动
docker run  -d -p 6379:6379  --name my-redis redis
# 查看运行状态
docker ps

Redis 命令

http://www.redis.cn/commands.html

RedisTemplate&序列化机制

引入依赖

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

指定 redis 地址

spring:
  redis:
    host: localhost

redis 常见 5 中数据类型

String 字符串
List 列表
Set 集合
Hash 散列
ZSet 有序集合

测试使用

package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
public class RedisTest {
    // k-v字符串形式
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    // k-v对象形式
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testRedis(){
        stringRedisTemplate.opsForValue().set("name", "Tom");
        String name = stringRedisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
}

保存对象:序列化后再保存

1、手动转换数据为 json

2、自定义序列化规则

package com.example.demo.config;
import com.example.demo.pojo.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@Configuration
public class MyRedisConfig {
    @Bean
    public RedisTemplate<Object, Employee> employeeRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Object, Employee> redisTemplate = new RedisTemplate<Object, Employee>();
        redisTemplate.setConnectionFactory(factory);
        // 设置序列化器
        Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<>(Employee.class);
        redisTemplate.setDefaultSerializer(serializer);
        return redisTemplate;
    }
}

测试

package com.example.demo;
import com.example.demo.pojo.Employee;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
public class RedisTest {
    @Autowired
    RedisTemplate<Object, Employee> employeeRedisTemplate;
    @Test
    public void testRedisSerializer(){
        Employee employee = new Employee();
        employee.setName("Tom");
        employee.setAge(23);
        employeeRedisTemplate.opsForValue().set("emp", employee);
    }
}

引入 redis-starter 之后,缓存组件使用 RedisCache

利用序列化保存数据,都是以 Object 形式保存,默认使用 jdk 序列化机制

可以保存为 json

相关实践学习
基于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
相关文章
|
2月前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
71 0
|
2天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
27 8
|
1月前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
148 5
|
2月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
73 9
|
3月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
46 9
|
2月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
37 0
|
3月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
30 1
|
3月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
120 2
|
3月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
337 1
|
3月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
43 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
下一篇
开通oss服务