springboot框架学习积累—SpringBoot缓存管理之相关组件
1.SpringBoot支持的缓存组件有哪些
- 在
SpringBoot中,数据的缓存管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cache和org.springframework.cache.CacheManager缓存管理器接口 - 如果当前程序没有定义类型为
CacheManager的Bean组件或者是名为cacheResolver缓存解析器,SpringBoot将尝试选择并启用以下缓存组件(按照指定顺序)
- Generic
- JCache (JSR-107) (EhCache3 、Hazelcast、 Infinispan等)
- EhCache 2.x
- Hazelcast
- Infinispan
- Couchbase
- Redis
- Caffeine
- Simple


2.SpringBoot基于注解的Redis缓存实现
- 添加redis的依赖启动器:由于引入了
Redis的依赖启动器,所以会将默认的SimpleCacheConfiguration缓存配置类变成RedisCacheConfiguration这个缓存配置类,容器中使用的缓存管理器也从ConcurrentMapCacheManager变成了RedisCacheManager,这时候缓存管理器创建的Cache是RedisCache,进而操作Redis进行数据的缓存
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>- 对Redis服务进行配置
#Redis服务地址
spring.redis.host=127.0.0.1
#Redis服务端口号
spring.redis.port=6379
#Redis服务密码
spring.redis.password=
#对基于注解的Redis缓存数据统一设置有效期为1分钟,单位毫秒
spring.cache.redis.time-to-live=60000- 编写业务层,实现Redis缓存逻辑
controller
/**
* @author yy
*/
@RestController
public class CommentController {
@Autowired
private CommentService commentService;
/**
* 查询
*
* @param id
* @return
*/
@RequestMapping(value = "/findCommentById")
public Comment findCommentById(Integer id){
Comment comment = commentService.findCommentById(id);
return comment;
}
/**
* 修改
*
* @param comment
* @return
*/
@RequestMapping("/updateComment")
public Comment updateComment(Comment comment){
Comment commentById = commentService.findCommentById(comment.getId());
commentById.setAuthor(comment.getAuthor());
Comment comment1 = commentService.updateComment(commentById);
return comment1;
}
/**
* 删除
*
* @param id
*/
@RequestMapping("/deleteComment")
public void deleteComment(Integer id){
commentService.deleteComment(id);
}service
/**
* @author yh
*/
@Service
public class CommentService {
@Autowired
private CommentRepository commentRepository;
/**
* @Cacheable: 将该方法查询结果comment存放在springboot默认Simple缓存中(前提是没有引入其他缓存组件)
* cacheNames: 起一个缓存命名空间 对应缓存唯一标识
* unless:当满足等号后面的条件时,结果不进入缓存
*/
@Cacheable(cacheNames = "comment",unless = "#result == null ")
public Comment findCommentById(Integer id){
Optional<Comment> byId = commentRepository.findById(id);
if (byId.isPresent()){
//获取comment对象
Comment comment = byId.get();
return comment;
}
return null;
}
/**
* 更新
*/
@CachePut(cacheNames = "comment",key = "#result.id")
public Comment updateComment(Comment comment){
commentRepository.updateComment(comment.getAuthor(),comment.getId());
return comment;
}
/**
* 删除
*/
@CacheEvict(cacheNames = "comment")
public void deleteComment(Integer id){
commentRepository.deleteById(id);
}
}3.SpringBoot基于API的Redis缓存实现

/**
* @author yh
*/
@Service
public class ApiCommentService {
@Autowired
private CommentRepository commentRepository;
@Autowired
private RedisTemplate redisTemplate;
/**
* 查询方法,使用API方式进行缓存。
* 先去缓存中查找,缓存中有直接返回,没有,查询数据库
*
* @param id
* @return
*/
public Comment findCommentById(Integer id){
//通过key找Object对象,get括号中的是key
Object o = redisTemplate.opsForValue().get("comment_" + id);
if (o!=null){
//查询到了数据直接返回
return (Comment) o;
}else {
//缓存中没有,去数据库中找
Optional<Comment> byId = commentRepository.findById(id);
if (byId.isPresent()){
//获取comment对象
Comment comment = byId.get();
//将查询结果放到缓存中,并且设置有效期
redisTemplate.opsForValue().set("comment_" + id,comment,1, TimeUnit.DAYS);
return comment;
}
}
return null;
}
/**
* 修改
*
* @param comment
* @return
*/
public Comment updateComment(Comment comment){
commentRepository.updateComment(comment.getAuthor(),comment.getId());
//将数据在数据库中修改完成,再存到redis库里面,将更新数据
redisTemplate.opsForValue().set("comment_" + comment.getId(),comment);
return comment;
}
/**
* 删除
*
* @param id
*/
public void deleteComment(Integer id){
commentRepository.deleteById(id);
redisTemplate.delete("comment_" + id);
}
}4.SpringBoot之Redis缓存默认序列化机制

- 查看源码,可以将源码分成两部分 1.声明了key,value各种序列化的初始值,初始值为空 2.进行默认序列化设置方式,默认设置是JDK序列化方式
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>,
BeanClassLoaderAware {
// 声明了key,value各种序列化的初始值,初始值为空
@Nullable
private RedisSerializer keySerializer = null;
@Nullable
private RedisSerializer valueSerializer = null;
@Nullable
private RedisSerializer hashKeySerializer = null;
@Nullable
private RedisSerializer hashValueSerializer = null;
...
// 进行默认序列化设置方式,默认设置是JDK序列化方式
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if(this.defaultSerializer == null) {
this.defaultSerializer = new JdkSerializationRedisSerializer(
this.classLoader != null?
this.classLoader:this.getClass().getClassLoader());
}
...
}
...
}
2. 根据上述源码分析可以得出以下两个重要结论



5.SpringBoot之Redis缓存自定义序列化机制
- 引入
Redis的依赖后,SpringBoot提供的RedisAutoConfiguration自动配置会生效,RedisAutoConfiguration这个类有关于RedisTemplate的定义方式
public class RedisAutoConfiguration {
//将方法的返回值注入到ioc容器中,key是方法名
@Bean
//当redisTemplate这个bean不存在时生效,如果自定义了一个redisTemplate的bean,那么这个方法的返回值就失效了
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
...
}


6.SpringBoot缓存管理之自定义RedisCacheManager

Redis注解默认序列化机制:RedisCacheConfiguration

@Configuration
class RedisCacheConfiguration {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory
redisConnectionFactory, ResourceLoader
resourceLoader) {
RedisCacheManagerBuilder builder =
RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(this.determineConfiguration(resourceLoader.getClassLoader()));
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
builder.initialCacheNames(new LinkedHashSet(cacheNames));
}
return
(RedisCacheManager) this.customizerInvoker.customize(builder.build());
}
private org.springframework.data.redis.cache.RedisCacheConfiguration
determineConfiguration(ClassLoader classLoader) {
if (this.redisCacheConfiguration != null) {
return this.redisCacheConfiguration;
} else {
Redis redisProperties = this.cacheProperties.getRedis();
org.springframework.data.redis.cache.RedisCacheConfiguration
config =
org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConf
ig();
config =
config.serializeValuesWith(SerializationPair.fromSerializer(
new
JdkSerializationRedisSerializer(classLoader)));
...
return config;
}
}
}

制,需要自定义RedisCacheManager
自定义RedisCacheManager

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
RedisSerializer<String> strSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jacksonSeial =
new Jackson2JsonRedisSerializer(Object.class);
// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);
// 定制缓存数据序列化方式及时效
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(strSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(jacksonSeial))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager
.builder(redisConnectionFactory).cacheDefaults(config).build();
return cacheManager;
}
















