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缓存值,当一个线程缓存成功后,其它线程便直接拿缓存后的数据,不会再去查库缓存,能解决缓存击穿问题;一个线程去新建,新建成功后其它线程才能拿

 

posted @ 2024-08-19 14:28  山阴路的秋天  阅读(46)  评论(0编辑  收藏  举报