springboot2.0整合redis自定义注解实现过期时间

前提
可以通过以下方法统一过期时间,就是不太实用

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        //设置缓存过期时间
        RedisCacheConfiguration redisCacheCfg=RedisCacheConfiguration.defaultCacheConfig()
                            .entryTtl(Duration.ofHours(1))
                            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER))
                            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON__SERIALIZER));
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheCfg)
                .build();
    }

自定义注解实现

1、实现思路:通过spring相关方法拿到所有 自定义的注解,将过期时间设置到对应key里

新建类RedisTimeCacheManager 继承 RedisCacheManager 重写loadCaches()方法
实现 ApplicationContextAware 用于通过 applicationContext 拿到所有 自定义的注解
实现 InitializingBean 用于执行 afterPropertiesSet方法

2、代码如下

/**
 * @author xhji
 */
@Slf4j
public class RedisTimeCacheManager extends RedisCacheManager implements ApplicationContextAware, InitializingBean {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    private Map initialCacheConfiguration = new LinkedHashMap<>();

    /**
     * key serializer
     */
    public static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();

    /**
     * value serializer
     * 
     *     使用 FastJsonRedisSerializer 会报错:java.lang.ClassCastException
     *     FastJsonRedisSerializer fastSerializer = new FastJsonRedisSerializer<>(Object.class);
     * 
     */

    public static final GenericFastJsonRedisSerializer FASTJSON_SERIALIZER = new GenericFastJsonRedisSerializer();

    /**
     * key serializer pair
     */
    public static final RedisSerializationContext.SerializationPair STRING_PAIR = RedisSerializationContext
            .SerializationPair.fromSerializer(STRING_SERIALIZER);
    /**
     * value serializer pair
     */
    public static final RedisSerializationContext.SerializationPair FASTJSON_PAIR = RedisSerializationContext
            .SerializationPair.fromSerializer(FASTJSON_SERIALIZER);

    public RedisTimeCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    @Override
    protected Collection loadCaches() {
        return initialCacheConfiguration.entrySet().stream()
                .map(entry -> super.createRedisCache(entry.getKey(),entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public void afterPropertiesSet() {
        Stream.of(applicationContext.getBeanNamesForType(Object.class))
                .forEach(beanName ->
                        add(applicationContext.getType(beanName))
                );
        super.afterPropertiesSet();
    }

    /**
     * 查询所有@CacheExpire的方法 获取过期时间
     * @param clazz
     */
    private void add(final Class clazz) {
        ReflectionUtils.doWithMethods(clazz, method -> {
            ReflectionUtils.makeAccessible(method);
            method.getAnnotation(CacheExpire.class);
            CacheExpire cacheExpire = AnnotationUtils.findAnnotation(method, CacheExpire.class);
            if (cacheExpire == null) {
                return;
            }
            Cacheable cacheable = AnnotationUtils.findAnnotation(method, Cacheable.class);
            if (cacheable != null) {
                add(cacheable.cacheNames(), cacheExpire);
                return;
            }
        }, method -> null != AnnotationUtils.findAnnotation(method, CacheExpire.class));
    }

    private void add(String[] cacheNames, CacheExpire cacheExpire) {
        for (String cacheName : cacheNames) {
            if (StringUtils.isBlank(cacheName)){
                continue;
            }
            long expire = cacheExpire.expire();
            TimeType type = cacheExpire.type();
            log.info("cacheName: {}, expire: {}", cacheName, expire);
            if (expire >= 0) {
                // 缓存配置
                RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(type.duration.apply(expire))
                        .disableCachingNullValues()
                        // .prefixKeysWith(cacheName)
                        .serializeKeysWith(STRING_PAIR)
                        .serializeValuesWith(FASTJSON_PAIR);
                initialCacheConfiguration.put(cacheName, config);
            } else {
                log.warn("{} use default expiration.", cacheName);
            }
        }
    }
}
 
  
/**
 * @author xhji
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 初始化一个RedisCacheWriter
        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);

        //设置默认缓存过期时间
        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig()
                            .entryTtl(Duration.ofHours(1))
                            .serializeKeysWith(RedisTimeCacheManager.STRING_PAIR)
                            .serializeValuesWith(RedisTimeCacheManager.FASTJSON_PAIR);
        return new RedisTimeCacheManager(cacheWriter, defaultCacheConfig);
    }

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        // 配置redisTemplate
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        // key序列化
        redisTemplate.setKeySerializer(RedisTimeCacheManager.STRING_SERIALIZER);
        // value序列化
        redisTemplate.setValueSerializer(RedisTimeCacheManager.FASTJSON_SERIALIZER);
        // Hash key序列化
        redisTemplate.setHashKeySerializer(RedisTimeCacheManager.STRING_SERIALIZER);
        // Hash value序列化
        redisTemplate.setHashValueSerializer(RedisTimeCacheManager.FASTJSON_SERIALIZER);
        // 如果 KeySerializer 或者 ValueSerializer 没有配置,则对应的 KeySerializer、ValueSerializer 才使用这个 Serializer
        redisTemplate.setDefaultSerializer(RedisTimeCacheManager.FASTJSON_SERIALIZER);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}
/**
 * @author xhji
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheExpire {
    /**
     * expire time, default 60s
     */
    @AliasFor("expire")
    long value() default 60L;

    /**
     * expire time, default 60s
     */
    @AliasFor("value")
    long expire() default 60L;

    /**
     * 时间单位
     *
     * @return
     */
    TimeType type() default SECONDS;

}
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.function.Function;

public enum TimeType {
    SECONDS(Duration::ofSeconds),
    MINUTES(Duration::ofMinutes),
    HOURS(Duration::ofHours),
    DAY(Duration::ofDays),
    WEEK(week -> {
        LocalDateTime now = LocalDateTime.now();
        return Duration.between(now, now.plusWeeks(week));
    }),
    MONTH(month -> {
        LocalDateTime now = LocalDateTime.now();
        return Duration.between(now, now.plusMonths(month));
    }),
    YEAR(year -> {
        LocalDateTime now = LocalDateTime.now();
        return Duration.between(now, now.plusYears(year));
    });

    TimeType(Function duration) {
        this.duration = duration;
    }

    public Function duration;
}

项目地址:https://gitee.com/xhji/spiderboot

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