spring cache设置指定key缓存过期时间

spring cache设置指定key缓存过期时间

    • Maven依赖
    • Cache配置类

第九更,spring cache设置指定key缓存过期时间,基于spring的生命周期,在创建CacheManager之前获取所有的cacheName,并根据分割符“#”切分cacheName,得到过期时间,并设置,不包含分割符的cacheName,使用默认过期时间(2天)。

Maven依赖

<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starterartifactId>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-cacheartifactId>
			<version>2.1.5.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-data-redisartifactId>
			<version>2.1.5.RELEASEversion>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
			<version>2.1.5.RELEASEversion>
		dependency>
	dependencies>

Cache配置类

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheOperation;
import org.springframework.cache.interceptor.CacheOperationSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.*;

import java.time.Duration;
import java.util.*;

@EnableCaching
@Configuration
public class CacheConfig implements ApplicationContextAware {


    private Set<String> cacheNames = new HashSet<>();

    private static final String SEPARATOR = "#";

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        //默认过期时间2天
        RedisCacheConfiguration defaultConfiguration = getRedisCacheConfigurationWithTtl(2 * 24 * 3600);
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager
                .builder(connectionFactory)
                .cacheDefaults(defaultConfiguration);
        if (!CollectionUtils.isEmpty(cacheNames)) {
            Map<String, RedisCacheConfiguration> cacheConfigurations = new LinkedHashMap<>();
            for (String cacheName : cacheNames) {
                if (cacheName.contains(SEPARATOR)) {
                    String[] strs = StringUtils.split(cacheName, SEPARATOR);
                    Assert.notNull(strs);
                    long ttl = Long.parseLong(strs[1].trim());
                    RedisCacheConfiguration customizedConfiguration = getRedisCacheConfigurationWithTtl(ttl);
                    cacheConfigurations.put(cacheName, customizedConfiguration);
                }
            }
            if (cacheConfigurations.size() > 0) {
                builder.withInitialCacheConfigurations(cacheConfigurations);
            }
        }
        return builder.build();

    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(long ttl) {
        return RedisCacheConfiguration
                .defaultCacheConfig()
                .disableCachingNullValues()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .entryTtl(Duration.ofSeconds(ttl));
    }

    //实现ApplicationContextAware接口的Bean会被提前实例化,这个方法会优先执行
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (!(applicationContext instanceof ConfigurableApplicationContext)) {
            return;
        }
        ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;
        //CacheOperationSource 可以被提前实例化,是spring cache提供的工具类
        CacheOperationSource cacheOperationSource = context.getBean(CacheOperationSource.class);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(beanName);
            try {
                Class<?> beanClass = beanDefinition.resolveBeanClass(ClassUtils.getDefaultClassLoader());
                if (beanClass != null) {
                    ReflectionUtils.doWithMethods(beanClass, m -> {
                                Collection<CacheOperation> cacheOperations = cacheOperationSource.getCacheOperations(m, beanClass);
                                if (!CollectionUtils.isEmpty(cacheOperations)) {
                                    for (CacheOperation operation : cacheOperations) {
                                        cacheNames.addAll(operation.getCacheNames());
                                    }
                                }
                            }
                    );
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(java,java,spring,redis)