springboot 缓存-cacheManager
日常项目中 如果对接口响应时间要求较高 通常需要结合redis对接口进行缓存处理。
1. pom 文件中引入redis jar
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
2.yml中添加redis 配置信息
redis: database: 0 password: 密码 jedis: pool: max-active: 8 max-wait: -1 max-idle: 8 min-idle: 0 cluster: nodes: 集群redis地址 max-redirects: 3 timeout: 5000
3.redisConfig 对 cacheManager处理
@Configuration @EnableAutoConfiguration public class RedisConfig { /** * 注入 RedisConnectionFactory */ @Autowired RedisConnectionFactory redisConnectionFactory; public static final Long DEFAULT_EXPIRE_TIME = 3600L; /** * 实例化 RedisTemplate 对象 * * @return */ @Bean public RedisTemplate<String, Object> functionDomainRedisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); initDomainRedisTemplate(redisTemplate, redisConnectionFactory); return redisTemplate; } /** * 设置数据存入 redis 的序列化方式 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setConnectionFactory(factory); } /*** * * 实例化 HashOperations 对象,可以使用 Hash 类型操作** * * @param redisTemplate * @return */ @Bean public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) { return redisTemplate.opsForHash(); } /** * 配置cacheManager */ @Bean(name = "cacheManager") public RedisCacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() // 设置缓存的默认过期时间 .entryTtl(Duration.ofSeconds(DEFAULT_EXPIRE_TIME)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // 不缓存空值 .disableCachingNullValues(); //根据redis缓存配置和reid连接工厂生成redis缓存管理器 RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .transactionAware() .build(); return redisCacheManager; } /*** * 配置jackson2JsonRedisSerializer * @return */ private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() { Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.configure(MapperFeature.USE_ANNOTATIONS, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); return jackson2JsonRedisSerializer; } }
4.在需要缓存的接口中进行 @Cacheable ,@CachePut,@CacheEvict 处理
例如:
@Cacheable(value = "test", key = "#deviceModel", unless = "#result == null")
@Cacheable:每次执行方法前都会检查cache中是否存在相同key的缓存,如果存在就不再执行该方法,直接从缓存中获取结果进行返回,如果不存在则会执行该方法并将结果存入指定key的缓存中
@CachePut: 在执行方法前不会去检查缓存中是否存在key的缓存,每次都会执行该方法,并将执行结果存入指定key的缓存中,使用在保存,更新方法中,标注在类上和方法
@CacheEvict: 标注在需要清除缓存的方法或类,标记在类上时表示其中所有方法的执行都会触发缓存的清除操作
cacheResolver属性:指定自定义的缓存管理器 cacheManager缓存管理器与cacheResolver自定义解析器二选一使用
condition属性:符合指定的条件才可以缓存,可以通过 SpEL 表达式进行设置
unless 属性:unless的条件为 true 时,方法的返回值不会被缓存
sync 属性:默认是false 异步模式下 unless 属性不可用 sync=true:同步模式,若多个线程尝试为同一个key缓存值,当一个线程缓存成功后,其它线程便直接拿缓存后的数据,不会再去查库缓存,能解决缓存击穿问题;一个线程去新建,新建成功后其它线程才能拿