redis可以用作数据库缓存 消息中间件
默认是ConcurrentMapCacheManager,创建的是ConcurrentMapCache组件,将数据保存在一个ConcurrentMap里面。
开发中经常使用的是缓存的中间件。
缓存的配置类:
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
在这里面导入相应的东西才会生效。
其他的配置什么时候开启?
自动配置的。
整合redis作为缓存:
redis中文网进行学习。Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
安装redis:docker的形式进行安装。
在浏览器输入docker hub上搜索和下载。
docker中国有镜像加速的功能。
docker pull registry.docker-cn.com/library/redis
启动镜像:
docker run -d -p 6379:6379 --name myredis docker.io/redis
docker run -d --name myredis -p 6379:6379 docker.io/redis --requirepass "123456"
开机启动镜像:
$ docker update --restart=always 81bcb97c4f5e(自己docker产生的id)
运行docker
安装redis的连接工具。
建立连接:
测试下redis的常用的数据操作:
右键打开控制台。
get msg
lpush集合 队列入队
lpop mylist 左边出
出队rpop mylist 右边出
set集合的操作:
sadd myset zhangsan lisi
sadd myset lisi
0是已经有了lisi
smembers myset
sismember myset wangwu
10----------------------------------------------------------------------------------------------------------------会了
引入redis的starter:
学习找下springboot的官方文档。
引入场景启动器
场景启动器,引入就启动起来了。
配置redis,只要指定下redis的主机地址,或者密码的地址。
spring.redis.host=192.168.244.130
测试:引入了redis的场景之后,就直接自动配置了。
就起作用了。
看下自动配置主要做了什么?
配置了两个东西:
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
* @author Christoph Strobl
* @author Phillip Webb
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Marco Aust
* @author Mark Paluch
*/
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
两个Template就和以前学的JDBSTempalte一样的。用的话只需要自动注入就可以。
用的话自动注入即可
package com.atguigu.cache;
import com.atguigu.cache.bean.Employee;
import com.atguigu.cache.mapper.EmployeeMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
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;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CacheApplicationTests {
@Autowired
EmployeeMapper employeeMapper;
@Autowired
StringRedisTemplate stringRedisTemplate; //操作k-v都是字符串的
@Autowired
RedisTemplate redisTemplate; //k-v都是对象的
@Test
public void contextLoads() {
Employee empById = employeeMapper.getEmpById(1);
System.out.println(empById);
}
/**
* Redis常见的五大数据类型
* String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
* stringRedisTemplate.opsForValue()[String(字符串)]
* stringRedisTemplate.opsForList()[List(列表)]
* stringRedisTemplate.opsForSet()[Set(集合)]
* stringRedisTemplate.opsForHash()[Hash(散列)]
* stringRedisTemplate.opsForZSet()[ZSet(有序集合)]
*/
@Test
public void test01(){
//给redis中保存数据
stringRedisTemplate.opsForValue().append("msg","hello");
String msg = stringRedisTemplate.opsForValue().get("msg");
System.out.println(msg);
stringRedisTemplate.opsForList().leftPush("mylist","1");
stringRedisTemplate.opsForList().leftPush("mylist","2");
}
}
redis的学习网站。
测试保存对象:
//测试保存对象
@Test
public void test02(){
Employee empById = employeeMapper.getEmpById(1);
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
redisTemplate.opsForValue().set("emp-01",empById);
//1、将数据以json的方式保存
//(1)自己将对象转为json
//(2)redisTemplate默认的序列化规则;改变默认的序列化规则;
//empRedisTemplate.opsForValue().set("emp-01",empById);
}
注意传的对象的前提必须是可序列化的:
查看redis:
这是序列化的结果。
要想可视化的查看有两种方法:
1.以对象转为json的方式保存。。。。。。。。。这个没有测试过。
2. 模型有序列化的规则:
默认的序列化器就是JDK的序列化器,我们自己写一个就可以了,注意写的不是序列化器是模板引擎。
复制这个即可。
package com.atguigu.cache.config;
import com.atguigu.cache.bean.Department;
import com.atguigu.cache.bean.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import java.net.UnknownHostException;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//放入一个序列化器
Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(ser);
return template;
}
/*@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
template.setDefaultSerializer(ser);
return template;
}
//CacheManagerCustomizers可以来定制缓存的一些规则
@Primary //将某个缓存管理器作为默认的
@Bean
public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}*/
}
在这里复制一下。
在测试类里面注入:
@Autowired
RedisTemplate<Object, Employee> empRedisTemplate;
//测试保存对象
@Test
public void test02(){
Employee empById = employeeMapper.getEmpById(1);
//默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
//redisTemplate.opsForValue().set("emp-01",empById);
//1、将数据以json的方式保存
//(1)自己将对象转为json
//(2)redisTemplate默认的序列化规则;改变默认的序列化规则;
empRedisTemplate.opsForValue().set("emp-01",empById);
}
代码如上。
直接改变序列化规则。
11----------------------------------------------------------------------------------------------------------------会了
上一节讲到了redisTemplate操作redis,这节我们测试缓存。
/**
* 一、搭建基本环境
* 1、导入数据库文件 创建出department和employee表
* 2、创建javaBean封装数据
* 3、整合MyBatis操作数据库
* 1.配置数据源信息
* 2.使用注解版的MyBatis;
* 1)、@MapperScan指定需要扫描的mapper接口所在的包
* 二、快速体验缓存
* 步骤:
* 1、开启基于注解的缓存 @EnableCaching
* 2、标注缓存注解即可
* @Cacheable 将方法的运行结果缓存
* @CacheEvict
* @CachePut
* 默认使用的是ConcurrentMapCacheManager==ConcurrentMapCache;将数据保存在 ConcurrentMap<Object, Object>中
* 开发中使用缓存中间件;redis、memcached、ehcache;
* 三、整合redis作为缓存
* Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
* 1、安装redis:使用docker;
* 2、引入redis的starter
* 3、配置redis
* 4、测试缓存
* 原理: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的序列化机制
* 4)、自定义CacheManager;
*
*/
原理:
debug=true:是自动配置的报告
之前的就不匹配了
为什么?
redis是匹配的。
可以看出这个要是起作用的话就是容器中没有CacheManager,所以优先级高的先覆盖掉。
先判断:引入redisStart以后给容器中放了一个缓存管理器:
这里是提前判断的并在容器中放入了缓存管理器。
点进去RedisManager创建Cache
给我们的是RedisCache。
整合redis作为缓存
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
1、安装redis:使用docker;
2、引入redis的starter
3、配置redis
4、测试缓存
原理: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的序列化机制
4)、自定义CacheManager;
缓存1号员工:
http://localhost:8080/emp/1 直接测试不用改代码的。
再次查询,发现不走数据库了,说明存到redis里面了。
发现是乱码是默认的jdk序列化的结果。
原理:来到RedisCacheConfiguration看下是如何创建的 这个是老版本的做法。
帮我们创建了。
注意上面的参数RedisTemplate<Object, Object>是RedisAutoConfiguration帮我们创建的,下面是源码:
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
* @author Christoph Strobl
* @author Phillip Webb
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Marco Aust
* @author Mark Paluch
*/
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
点进去默认用的序列化的机制是jdk的。
所以我们自定义自己的Cachemanager:
按照这个自己写.
1.0和2.0区别很大停更。07:56
其实就是重写了这个方法。
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
新版的代码 注意区别 其实思想都是一样的。 自己操作就是重写redisTemplate 用作缓存就是重写CacheManager。
package com.atguigu.cache.config;
import com.atguigu.cache.bean.Department;
import com.atguigu.cache.bean.Employee;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(ser);
return template;
}
/*@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
template.setDefaultSerializer(ser);
return template;
}*/
//CacheManagerCustomizers可以来定制缓存的一些规则
/*@Primary //将某个缓存管理器作为默认的
@Bean
public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(RedisCacheManager);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}*/
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
/*@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}*/
}
上面的是新版的。
进入RedisCacheConfiguration。
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.cache;
import java.util.List;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
/**
* Redis cache configuration.
*
* @author Stephane Nicoll
* @since 1.3.0
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@ConditionalOnBean(RedisTemplate.class)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class RedisCacheConfiguration {
private final CacheProperties cacheProperties;
private final CacheManagerCustomizers customizerInvoker;
RedisCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
}
@Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return this.customizerInvoker.customize(cacheManager);
}
}
判断条件:系统默认得缓存管理器得条件是容器中没有CacheManager,但是我们现在向容器中抛入了一个CacheManager。就被替换了。
重启进行测试:
可以了。
注意上图有一个前缀就是cacheName("emp")这是为什么呢
创建Deptservice。
package com.atguigu.cache.service;
import com.atguigu.cache.bean.Department;
import com.atguigu.cache.bean.Employee;
import com.atguigu.cache.mapper.DepartmentMapper;
import com.atguigu.cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class DeptService {
@Autowired
DepartmentMapper departmentMapper;
@Autowired
EmployeeMapper employeeMapper;
/**
* 缓存的数据能存入redis;
* 第二次从缓存中查询就不能反序列化回来;
* 存的是dept的json数据;CacheManager默认使用RedisTemplate<Object, Employee>操作Redis
*
*
* @param id
* @return
*/
@Cacheable(cacheNames = "dept")//默认会将cachenames作为key的前缀
public Department getDeptById(Integer id){
System.out.println("查询部门"+id);
Department department = departmentMapper.getDeptById(id);
return department;
}
}
开始查询:
第二次:走缓存,2.0的没有问题。新版和员工解耦了。1.0没解耦有问题,只能存缓存但是不能反序列化回来。
原因是存的dept得JSON数据,而取的是employee的缓存。
老版本的解决办法:重新写一套。
指定使用CacheManager:
类上指定总的
方法上指定
-------------------------------------------------------------------------------------------------------------------------------------------------
有多个manager的时候,在配置类里面写上默认的缓存管理器。不指定缓存管理器就用默认的。
把这个拷贝到config里面,应该设置这个是默认的。
注意配置类也要指定。
新老版本的配置对比:
package com.atguigu.cache.config;
import com.atguigu.cache.bean.Department;
import com.atguigu.cache.bean.Employee;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
template.setDefaultSerializer(ser);
return template;
}
/*@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
template.setDefaultSerializer(ser);
return template;
}*/
//CacheManagerCustomizers可以来定制缓存的一些规则
/*@Primary //将某个缓存管理器作为默认的
@Bean
public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(RedisCacheManager);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}*/
private Duration timeToLive = Duration.ZERO;
public void setTimeToLive(Duration timeToLive) {
this.timeToLive = timeToLive;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(timeToLive)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
/*@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//key多了一个前缀
//使用前缀,默认会将CacheName作为key的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}*/
}
--------------------------------------------------------------------------------------------------------------------------------------
最后一个知识点:
public Department getDeptById(Integer id){
System.out.println("查询部门"+id);
Department department = departmentMapper.getDeptById(id);
//获取某个缓存
Cache dept = cacheManager.getCache("dept");
dept.put("dept:123",department);
return department;
}
上面的是新版的。
老版的 明确指定id为deptCachemanager的。
注入cacheManager;
12-------------------------------------------------------------------------------------------------------------
代码的github地址:https://github.com/FandyWw/springboot-01-cache-my
-------------------------深入 指定配置文件启动
指定配置文件:https://blog.csdn.net/qq_30644579/article/details/83537529