springBoot17_缓存:环境搭建、原理、Cacheable、CachePut、CacheEvit、Caching、阿里云镜像加速、整合redis作为缓存、缓存原理、自定义缓存
JSR107规范的缓存
spring缓存抽象来简化缓存开发
环境搭建
导入依赖
建表、创建javaBean
连接数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 会根据连接自动判断,可以不写
#开启驼峰命名匹配规则
mybatis.configuration.map-underscore-to-camel-case=true
#打印日志
logging.level.com.sjg.cache.mapper=debug
使用注解mybatis
@Repository //或者@Mapper
public interface EmployeeMapper {@Select("select * from employee where id = #{id}")public Employee getEmpById(Integer id);@Update("update employee set lastName=#{lastName}, email=#{email}, gender=#{gender}, d_id=#{dId} where id=#{id}")public void updateEmp(Employee employee);@Delete("delete from employee where id=#{id}")public void deleteEmpById(Integer id);@Insert("insert into employee(lastName, email, gender, d_id) values(#{lastName}, #{email}, #{gender}, #{dId})")public void insertEmp(Employee employee);
}
主程序配置注解扫描
@RestController
public class EmployeeController {@AutowiredEmployeeService employeeService;@GetMapping("/emp/{id}")public Employee getEmployee(@PathVariable("id") Integer id){Employee emp = employeeService.getEmp(id);return emp;}
}
使用缓存
开启注解缓存
将方法返回值保存到缓存,如果再使用相同数据,直接取缓存
@Service
public class EmployeeService {@AutowiredEmployeeMapper employeeMapper;//将方法运行结果缓存,这样以后用到相同数据,直接从缓存取,不用调用方法从数据库查询@Cacheable(cacheNames = {"emp"})public Employee getEmp(Integer id){System.out.println("查询" + id + "员工");Employee emp = employeeMapper.getEmpById(id);return emp;}
}
原理:
* 1、自动配置类;CacheAutoConfiguration
* 2、缓存的配置类
* org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
* org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
* org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
* org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
* org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
* org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
* org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
* org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
* org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
* org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】
* org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
* 3、哪个配置类默认生效:SimpleCacheConfiguration;
*
* 4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager
* 5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;
*
* 运行流程:
* @Cacheable:
* 1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
* (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
* 2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
* key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;
* SimpleKeyGenerator生成key的默认策略;
* 如果没有参数;key=new SimpleKey();
* 如果有一个参数:key=参数的值
* 如果有多个参数:key=new SimpleKey(params);
* 3、没有查到缓存就调用目标方法;
* 4、将目标方法返回的结果,放进缓存中
*
* @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
* 如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;
*
* 核心:
* 1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
* 2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator
可用的spEL
Cacheable调用时机:调用方法前,先看缓存里有没有缓存,没有再调方法
1、指定缓存的key:默认是方法的参数作为key,可以使用spEL表达式进行改变
比如这里我使用当前方法名和参数作为key 即getEmp[2]
还可以使用key生成器
自定义生成器,并放到容器中,
@Configuration
public class MyCacheConfig {//自定义缓存key的生成策略@Bean("myKeyGenerator")public KeyGenerator keyGenerator(){return new KeyGenerator(){@Overridepublic Object generate(Object o, Method method, Object... params) {return method.getName()+"["+ Arrays.asList(params).toString()+"]";}};}
}
这次我使用自己定义的key生成器
condition:符合条件才缓存
比如这里表示获取的第一个参数值大于1才缓存
unless:如果,则不
比如这里,如果第一个参数值为2,则不缓存
sync:是否使用异步模式,与unless冲突
CachePut
调用时机:先调用目标方法, 把方法结果放进缓存,也就是最后才把结果放到缓存
- @CachePut:既调用方法,又更新缓存数据;同步更新缓存
- 修改了数据库的某个数据,同时更新缓存;
- 运行时机:
- 1、先调用目标方法
- 2、将目标方法的结果缓存起来
- 测试步骤:
- 1、查询1号员工;查到的结果会放在缓存中;
key:1 value:lastName:张三
- 2、以后查询还是之前的结果
- 3、更新1号员工;【lastName:zhangsan;gender:0】
将方法的返回值也放进缓存了;
key:传入的employee对象 值:返回的employee对象;
- 4、查询1号员工?
应该是更新后的员工;
key = "#employee.id":使用传入的参数的员工id;
key = "#result.id":使用返回后的id
@Cacheable的key是不能用#result
为什么是没更新前的?【1号员工没有在缓存中更新】
可以使用#employee.id作为key,也可以用#result.id作为key,因为CachePut是执行完方法才把数据放到缓存,也就是此时得到了返回值,即更新结果
要保证查询和更新,更新到的是同一个key的值
流程梳理:前提我不指定更新方法中的key,也就是默认使用的是返回值作为key。
首先,执行查询方法,会先看缓存中是否有key为1的缓存,发现没有,就去执行方法,查询数据库,是将参数id=1作为key,值是返回结果emp对象
当执行更新操作时,逻辑不同,会首先执行方法,也就是更新操作,更新数据库后返回,那么方法参数emp作为key,返回结果emp作为值
这就导致更新操作执行了,但是缓存中放的对象却因为key的缘故似乎没有得到更新。
所以要保证更新和查询是同一个key,也就是我在更新方法注解中标明result.id
CacheEvit
Caching
当需要定义复杂的缓存规则时,可以使用caching
@CacheConfig(cacheNames = “emp”) 可以抽取缓存中的公共配置
使用redis缓存
默认使用的是ConcurrentMapCacheManager==ConcurrentMapCache;将数据保存在 ConcurrentMap<Object, Object>中
但是开发中使用缓存中间件;redis、memcached、ehcache;
当完成redis相关配置时,才会使用redis缓存
1、下载redis镜像
dockerhub
但是下载是连接的国外的仓库,速度慢
这里我使用
阿里云docker CE镜像源站
阿里云镜像加速
CentOS7安装
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start
详情见官方文档
版本校验
root@iZbp12adskpuoxodbkqzjfZ:$ docker version
如果要使用阿里云容器镜像加速服务,
使用加速器可以提升获取Docker官方镜像的速度
需要注册阿里云,会生成专属你的加速器地址,然后根据操作文档配置加速器,重启docker即可
运行redis镜像
首先查看docker images
[root@localhost ~]# docker images
-d后台运行
-p暴露端口,redis默认端口是6379,将虚拟机的6379端口映射到redis6379,
–name为redis起名
接着指定运行哪个docker镜像
[root@localhost ~]# docker run -d -p 6379:6379 --name myredis docker.io/redis
运行起来后成为docker容器
建立redis连接
右键打开控制台测试
整合redis作为缓存
开发文档中找到redis starter
引入
spring-boot-starter-data-redis
配置redis
连接redis
测试
测试保存对象
先保证对象可序列化
redis保存对象,默认使用jdk序列化机制,但是保存的数据不易查看
1、可以使用json方式保存
自定义序列化器
修改redis中的序列化工具
配置自己的序列化器
@Configuration
public class MyRedisConfig {@Beanpublic RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {RedisTemplate<Object, Employee> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);//json序列化器Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);template.setDefaultSerializer(ser);return template;}
}
注入并使用
@AutowiredRedisTemplate<Object, Employee> empRedisTemplate;@Testpublic void test01(){//给redis保存数据
// stringRedisTemplate.opsForValue().append("msg", "hello");String msg = stringRedisTemplate.opsForValue().get("msg");System.out.println(msg);}
这样就修改了默认的序列化规则,不再是jdk的序列化
缓存原理
原理:CacheManager===Cache 缓存组件来实际给缓存中存取数据
1)、引入redis的starter,容器中保存的是 RedisCacheManager;
2)、RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据的
3)、默认保存数据 k-v 都是Object;利用序列化保存;如何保存为json
1、引入了redis的starter,cacheManager变为 RedisCacheManager;
2、默认创建的 RedisCacheManager 操作redis的时候使用的是 RedisTemplate<Object, Object>
3、RedisTemplate<Object, Object> 是 默认使用jdk的序列化机制
当引入redis的starter后,缓存管理器就不是默认的,而是RedisCacheManager,默认的RedisCacheManager操作redis使用的是RedisTemplate的序列化器,这个序列化器使用的是jdk的序列化。所以我们要修改缓存管理器的序列化工具
自定义缓存管理器
//自定义缓存管理器//缓存的数据存入redis,第二次再反序列化从缓存中查询出来@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofDays(1)).disableCachingNullValues().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();}
这样就修改为json方式序列化和反序列化来保存对象
springBoot17_缓存:环境搭建、原理、Cacheable、CachePut、CacheEvit、Caching、阿里云镜像加速、整合redis作为缓存、缓存原理、自定义缓存相关推荐
- docker配置阿里云镜像加速、镜像和容器常用命令、docker镜像原理
6. Docker 配置阿里镜像加速服务 6.1 docker 运行流程 6.2 docker配置阿里云镜像加速 查看自己的镜像加速地址(链接直达):https://cr.console.aliyun ...
- Springboot整合Redis,高并发下访问缓存与写入缓存
1.配置Redis连接:添加pox.xml依赖: <!-- redis --><dependency><groupId>org.springframework.bo ...
- java底层原理书籍_不愧是阿里p8大佬!终于把Java 虚拟机底层原理讲清楚了,请签收...
概述 JVM 的内存模型和 JVM 的垃圾回收机制一直是 Java 业内从业者绕不开的话题(实际调优.面试)JVM是java中很重要的一块知识,也是面试常问的问题之一,直至今天,仍然还有许多面试者在被 ...
- liunx 环境-配置docker阿里云镜像加速
1.登录阿里云 注册 2.找到控制台 1.创建一个目录 sudo mkdir -p /etc/docker 2.配置自己镜像加速器 sudo tee /etc/docker/daemon.json & ...
- 09、环境-配置docker阿里云镜像加速、通过阿里云控制台找到镜像加速器
1.访问阿里云 官网地址 https://www.aliyun.com/ 2.登录阿里云 3.点击控制台,找到镜像加速器 4.配置镜像加速器 sudo mkdir -p /etc/docker sud ...
- 分布式基础篇1——环境搭建(谷粒商城)
一.项目简介 1.电商模式 2.项目前置知识 3.项目技术&特色 4.项目架构图 5.微服务划分图 二.分布式基础概念 1.微服务 2.集群&分布式&节点 3.远程调用 4.负 ...
- 谷粒商城项目篇1_分布式基础篇_分布式基础概念、环境搭建、创建项目
写在前面 为丰富项目经验,特此学习B站开源视频<全网最强电商教程<谷粒商城>对标阿里P6/P7,40-60万年薪>希望通过此学习能巩固所学,将技术栈串接起来. 此项目三个阶段 ...
- Redis-学习笔记01【Redis环境搭建】
Java后端 学习路线 笔记汇总表[黑马程序员] Redis-学习笔记01[Redis环境搭建] Redis-学习笔记02[Redis命令操作] Redis-学习笔记03[Redis持久化] Redi ...
- 谷粒商城笔记+踩坑(1)——架构、项目环境搭建、代码生成器
导航: 谷粒商城笔记+踩坑汇总篇_谷粒商城笔记踩坑6_vincewm的博客-CSDN博客 目录 1.项目介绍 1.1 微服务架构图 1.2. 微服务划分图 2.项目环境搭建 2.1. 虚拟机搭建环境 ...
- Jeecg-Boot 快速开发平台,前后端分离—开发环境搭建
目录索引: 前端开发环境搭建 安装开发工具 导入项目 后端开发环境搭建 安装开发工具 导入项目 第一部分: 前端开发环境搭建 一.安装开发工具 安装nodejs.webstrom.yarn,安装方法参 ...
最新文章
- msm8953+android8.1接听电话时声音由默认听筒输出改为外放输出
- VTK:图片之ImageStack
- 表示探索、探究的几个词
- Doris之动态分区(全面)
- VS2017编译OpenJDK,编译通过的工程包下载链接
- 日期,时间相关R代码
- 推荐系统(7):推荐算法之基于协同过滤推荐算法
- 亚马逊SP-API市场端点接口文档整理
- 平均数、中位数、众数 三者的联系与区别
- 2017CNCC会议总结(一)
- 亮相Google I/O,字节跳动是这样应用Flutter的
- 湖南天才少女姚婷:刚毕业就被华为156万年薪邀请,来历不简单
- nsfw什么颜色_“ NSFW”是什么意思,以及如何使用它?
- 黑马C++学习总结之对象的初始化和清理
- 迅睿cms微信抖音小程序生成管理系统V1.0开源
- [数据结构] UVa1471 Defense Lines 防线
- 软件产品案例分析——福州大学微信小程序
- vim自动补全插件:YouCompleteMe使用前需要做的准备工作随手记录
- 4|无线传感器网络与应用|无线传感器网络原理及方法-许毅版|考试知识点
- 机器学习项目2-葡萄酒质量和年份的关系