springboot框架学习积累—SpringBoot缓存管理之相关组件
1.SpringBoot支持的缓存组件有哪些
在SpringBoot中,数据的缓存管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cache和org.springframework.cache.CacheManager缓存管理器接口如果当前程序没有定义类型为CacheManager的Bean组件或者是名为cacheResolver缓存解析器,SpringBoot将尝试选择并启用以下缓存组件(按照指定顺序)
GenericJCache (JSR-107) (EhCache3 、Hazelcast、 Infinispan等)EhCache 2.xHazelcastInfinispanCouchbaseRedisCaffeineSimple
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
@RestController
public class CommentController {
@Autowired
private CommentService commentService
;
@RequestMapping(value
= "/findCommentById")
public Comment
findCommentById(Integer id
){
Comment comment
= commentService
.findCommentById(id
);
return comment
;
}
@RequestMapping("/updateComment")
public Comment
updateComment(Comment comment
){
Comment commentById
= commentService
.findCommentById(comment
.getId());
commentById
.setAuthor(comment
.getAuthor());
Comment comment1
= commentService
.updateComment(commentById
);
return comment1
;
}
@RequestMapping("/deleteComment")
public void deleteComment(Integer id
){
commentService
.deleteComment(id
);
}
service
@Service
public class CommentService {
@Autowired
private CommentRepository commentRepository
;
@Cacheable(cacheNames
= "comment",unless
= "#result == null ")
public Comment
findCommentById(Integer id
){
Optional
<Comment> byId
= commentRepository
.findById(id
);
if (byId
.isPresent()){
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缓存实现
@Service
public class ApiCommentService {
@Autowired
private CommentRepository commentRepository
;
@Autowired
private RedisTemplate redisTemplate
;
public Comment
findCommentById(Integer id
){
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
= byId
.get();
redisTemplate
.opsForValue().set("comment_" + id
,comment
,1, TimeUnit
.DAYS
);
return comment
;
}
}
return null
;
}
public Comment
updateComment(Comment comment
){
commentRepository
.updateComment(comment
.getAuthor(),comment
.getId());
redisTemplate
.opsForValue().set("comment_" + comment
.getId(),comment
);
return comment
;
}
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
{
@Nullable
private RedisSerializer keySerializer
= null
;
@Nullable
private RedisSerializer valueSerializer
= null
;
@Nullable
private RedisSerializer hashKeySerializer
= null
;
@Nullable
private RedisSerializer hashValueSerializer
= null
;
...
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 {
@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
) {
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
;
}