* Redis是一个开源的,内存中的数据机构存储系统,它可以作为数据库,缓存和消息中间件。
* 使用:安装redis,引入redis的starter,配置redis
* 原理:CacheManager == Cache 缓存组件来实际给缓存中存取数据,替换默认的SimpleCacheConfiguration
* 1.引入redis的starter,容器中保存的是RedisCacheManager
* 2.RedisCacheManager 底层帮我们创建RedisCache来作为缓存组件:RedisCache通过操作redis缓存数据的
* 3.默认保存数据 k-v 都是Object,利用序列化保存的(需转换json)
* 附 SimpleCacheConfiguration和RedisCacheConfiguration 底层配置对比:
* @Configuration(proxyBeanMethods = false)
* @ConditionalOnMissingBean({CacheManager.class}) //SimpleCacheConfiguration起作用是容器中没有CacheManager
* @Conditional({CacheCondition.class})
* class SimpleCacheConfiguration {}
*
* @Configuration(proxyBeanMethods = false)
* @ConditionalOnClass({RedisConnectionFactory.class})
* @AutoConfigureAfter({RedisAutoConfiguration.class})
* @ConditionalOnBean({RedisConnectionFactory.class})
* @ConditionalOnMissingBean({CacheManager.class}) //redis也需要判断容器中没有CacheManager才生效
* @Conditional({CacheCondition.class})
* class RedisCacheConfiguration {}
* 原因:
* 1.引入redis的starter,cacheManager变为RedisCacheManager,剩下的CacheManager就不起作用了
* 2.默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>
* 3.RedisTemplate<Obejct,Object>是默认使用【jdk的序列化机制】
* 4.自定义CacheManager在MyRedisConfig中
* 使用:
* 常用类型:String list(列表) Set(集合) Hash(散列) ZSet(有序集合)
* stringRedisTemplate.opsForValue();
* stringRedisTemplate.opsForList();
* stringRedisTemplate.opsForSet();
* stringRedisTemplate.opsForHash();
* stringRedisTemplate.opsForZSet();
导入坐标(版本根据springboot走):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
配置文件:
spring.redis.host=localhost
spring.cache.redis.use-key-prefix=true #使用CacheName作为key的前缀
基于Springboot1.x配置RedisCacheManager
import com.bootbootboot.springboot01cache.bean.Department;
import com.bootbootboot.springboot01cache.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;
/**
* springboot 1.X 版本RedisCacheManager配置
*/
@Configuration
public class MyRedisConfig {
@Bean
//@ConditionalOnMissingBean
public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
template.setConnectionFactory(redisConnectionFactory);
//获取jackson序列化器
Jackson2JsonRedisSerializer<Employee> ser = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
//设置序列化器
template.setDefaultSerializer(ser);
return template;
}
@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Department> ser = new Jackson2JsonRedisSerializer<Department>(Department.class);
template.setDefaultSerializer(ser);
return template;
}
/**
* 这里可以扩展使用自定义的RedisTemplate<Object,Object>自定义缓存
*/
//CacheManagerCustomizers可以来定制缓存的一些规则
@Primary //将某个管理器设为默认
@Bean
public RedisCacheManager employeeCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//使用CacheName作为key的前缀,可在application配置文件中开启
//cacheManager.setUserPrefix(true);
return cacheManager;
}
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//cacheManager.setUserPrefix(true);
return cacheManager;
}
}
基于Springboot2.x配置RedisCacheManager
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.time.Duration;
import java.util.Objects;
/**
* springboot 2.X 版本的RedisManager配置
* 注意:
* 在配置文件中使用CacheName作为key的前缀:spring.cache.redis.use-key-prefix=true
* 在spring-boot2.x之前:RedisCacheManager cacheManager = new RedisCacheManager(RedisTemplate redisTemplate);
* 在spring-boot2.0之后:RedisCacheManager cacheManager = new RedisCacheManager(RedisCacheWriter redisCacheWriter,RedisCacheConfiguration redisCacheConfiguration);
*/
@Configuration
public class MyRedisCacheConfig {
//spring-boot2.x之前
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
}
//spring-boot2.0之后
@Bean //给容器注册一个Bean,返回缓存管理器,这里redisTemplate容器中有,所以会自动注入
public CacheManager MyRedisCacheConfig(RedisTemplate redisTemplate) {
//1.创建RedisCacheWriter
/**
* 非锁方式:nonLockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
* 有锁方式:lockingRedisCacheWriter(RedisConnectionFactory connectionFactory);
*/
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
//2.创建Jackson对象并传入需要序列化的对象
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
//3.传入 Jackson对象 并获取 RedisSerializationContext对象
RedisSerializationContext<Object, Object> serializationContext = RedisSerializationContext.fromSerializer(serializer);
//4.配置RedisCacheConfiguration
/**
* RedisCacheConfiguration.defaultCacheConfig()
* 设置 value 的序列化 serializeValuesWit(SerializationPari<?> valueSerializationPari)
* 设置 key 的序列化 serializeKeysWith(SerializationPari valueSerializationPari)
*/
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationContext.getValueSerializationPair());
//5.创建RedisCacheManager(RedisCacheWriter redisCacheWriter, RedisCacheConfiguration redisCacheConfiguration)对象并返回
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
//spring-boot2.0之后简化版
@Bean(name = "MyRedisCacheManager")
public CacheManager MyRedisCacheManagerSimple(RedisTemplate redisTemplate) {
return new RedisCacheManager(
RedisCacheWriter
.nonLockingRedisCacheWriter(Objects
.requireNonNull(redisTemplate
.getConnectionFactory())),
RedisCacheConfiguration
.defaultCacheConfig()
.serializeValuesWith(
RedisSerializationContext
.fromSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class))
.getValueSerializationPair()
)
);
}
}
使用:
@Service
public class EmployeeServiceForRedisService {
@Autowired
private DepartmentMapper departmentMapper;
@Autowired
RedisTemplate redisTemplate; //key-value都是对象
@Autowired
RedisTemplate<Object, Employee> empRedisTemplate; //使用特定对象的redistemplate
@Qualifier("deptCacheManager") //使用注解方式指定使用某个缓存管理器
@Autowired //sprintboot 1.x 中配置的CacheManager
RedisCacheManager deptCacheManager;
@Qualifier("MyRedisCacheManager") //springboot 2.x 中配置的CacheManager
@Autowired
CacheManager MyRedisCacheConfigSimple;
/**
* Redis是一个开源的,内存中的数据机构存储系统,它可以作为数据库,缓存和消息中间件。
* 使用:安装redis,引入redis的starter,配置redis
* 原理:CacheManager == Cache 缓存组件来实际给缓存中存取数据,替换默认的SimpleCacheConfiguration
* 1.引入redis的starter,容器中保存的是RedisCacheManager
* 2.RedisCacheManager 底层帮我们创建RedisCache来作为缓存组件:RedisCache通过操作redis缓存数据的
* 3.默认保存数据 k-v 都是Object,利用序列化保存的(需转换json)
* 附:
* @Configuration(proxyBeanMethods = false)
* @ConditionalOnMissingBean({CacheManager.class}) //SimpleCacheConfiguration起作用是容器中没有CacheManager
* @Conditional({CacheCondition.class})
* class SimpleCacheConfiguration {}
*
* @Configuration(proxyBeanMethods = false)
* @ConditionalOnClass({RedisConnectionFactory.class})
* @AutoConfigureAfter({RedisAutoConfiguration.class})
* @ConditionalOnBean({RedisConnectionFactory.class})
* @ConditionalOnMissingBean({CacheManager.class}) //redis也需要判断容器中没有CacheManager才生效
* @Conditional({CacheCondition.class})
* class RedisCacheConfiguration {}
* 原因:
* 1.引入redis的starter,cacheManager变为RedisCacheManager,剩下的CacheManager就不起作用了
* 2.默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>
* 3.RedisTemplate<Obejct,Object>是默认使用【jdk的序列化机制】
* 4.自定义CacheManager在MyRedisConfig中
* 常用类型:String list(列表) Set(集合) Hash(散列) ZSet(有序集合)
* stringRedisTemplate.opsForValue();
* stringRedisTemplate.opsForList();
* stringRedisTemplate.opsForSet();
* stringRedisTemplate.opsForHash();
* stringRedisTemplate.opsForZSet();
*/
public void saveStringType() {
//保存数据
stringRedisTemplate.opsForValue().append("msg", "hello");
stringRedisTemplate.opsForList().leftPush("myList", "2");
//读取数据
String msg = stringRedisTemplate.opsForValue().get("msg");
}
public void saveBeanType() {
Employee empById = employeeMapper.getEmpById(1);
//默认如果保存对象(对象需实现Serializable接口),使用jdk序列化机制,序列化后的数据保存到redis中
redisTemplate.opsForValue().set("emp-01", empById);
/**
* 将数据以json方式保存
* 1.自己将对象转为json
* 2.redisTemplate实现自己的序列化机制
*/
empRedisTemplate.opsForValue().set("emp-01", empById);
}
/**
* 使用配置缓存
* 注意:
* 如果使用的JPA,不要使用findById(id).get() 来返回对象;会反序列化失败。
*/
@Cacheable(cacheNames = "dept",key = "#id", cacheManager = "deptCacheManager") //springboot 1.X
// @Cacheable(cacheNames = "dept",key = "#id", cacheManager = "MyRedisCacheConfig") //springboot 2.X
public Department getDeptById(Integer id) {
Department department = departmentMapper.getDeptById(id);
return department;
}
/**
* 使用缓存管理器得到缓存:
* @Qualifier("deptCacheManager") //指定使用某个缓存管理器
* @Autowired
* RedisCacheManager deptCacheManager;
*/
public Department getDeptById2(Integer id) {
Department department = departmentMapper.getDeptById(id);
//获取某个缓存
Cache dept = deptCacheManager.getCache("dept");
dept.put("dept:1", department);
return department;
}
}