目录
article
SpringBoot & CacheManager
SpringBoot & CacheManager
- 使用注解
@EnableCaching启用缓存- 一般是添加在自定义 CacheManager 的配置类上
- 使用
@Cacheable、@CachePut、@CacheEvict来维护缓存@Cacheable:先查询缓存,不存在时才执行方法体@CachePut:始终执行方法体,并更新缓存@CacheEvict:始终执行方法体,并删除缓存- 接口方法为实体类型,而缓存 Key 只使用了其中的字段时,通过 key 参数来指定,格式为
#参数变量名.字段名
- 使用
RedisCacheManagerBuilderCustomizer来配置缓存- 这里使用的 Jackson 来
MyCacheConfiguration.java
自定义缓存 Key 和 Value 的序列化方法。
这里使用带类型的 Json 序列化方法。如果不带类型,在反序列化时,会自动反序列化为 HashMap 类型,从而导致在转换为方法的返回值时转型失败。
package com.mokasz.zhyx.hyperion.free.novel.core.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mokasz.zhyx.hyperion.free.novel.core.constant.CacheName;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration(proxyBeanMethods = false)
@EnableCaching
public class MyCacheConfiguration {
@Bean
public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
valueSerializer.setObjectMapper(mapper);
return (builder) -> builder
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer)))
.withCacheConfiguration(CacheName.NOVEL_DETAIL, RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ZERO)
.disableCachingNullValues()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer)));
}
}
NovelServiceImpl.java
缓存 Key 默认为指定的 value + :: + 所有参数。
package com.mokasz.zhyx.hyperion.free.novel.bll.service.impl;
import com.mokasz.zhyx.hyperion.free.novel.bll.service.NovelService;
import com.mokasz.zhyx.hyperion.free.novel.core.constant.CacheName;
import com.mokasz.zhyx.hyperion.free.novel.dao.entity.Novel;
import com.mokasz.zhyx.hyperion.free.novel.dao.service.NovelDaoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
@Slf4j
public class NovelServiceImpl implements NovelService {
private final NovelDaoService novelDaoService;
@Cacheable(value = CacheName.NOVEL_DETAIL, unless = "#result == null")
@Override
public Novel getNovel(int id) {
return this.novelDaoService.getById(id);
}
@CachePut(value = CacheName.NOVEL_DETAIL, key = "#novel.id", unless = "#result == null")
@Override
public Novel createNovel(Novel novel) {
this.novelDaoService.createNovel(novel);
return this.novelDaoService.getById(novel.getId());
}
@CachePut(value = CacheName.NOVEL_DETAIL, key = "#novel.id", unless = "#result == null")
@Override
public Novel updateNovel(Novel novel) {
this.novelDaoService.updateNovel(novel);
return this.novelDaoService.getById(novel.getId());
}
@CacheEvict(CacheName.NOVEL_DETAIL)
@Override
public boolean deleteNovel(Integer id) {
return this.novelDaoService.removeById(id);
}
}