springboot使用cache集成redis(自定义每个key过期时间)

@Cacheable是SpringCache的注解

当初见到这个注解以为是redis的,后来研究发现是个spring的全家桶,缓存器可以使用 ehCache,Redis,ConcurrentHashMap(jvm),ehCache研究的不多,好像和jvm内存一样做不到分布式。本文就redis做自定义key过期设置

支持配置的key过期时间

采用springboot 2.4.0 版本,发现这个版本对配置文件做了优化;比如:
配置了dev之后,dev.yml 和 dev.properties都会生效
在这里插入图片描述

配置文件
# cacheName:过期时间;逗号分隔
xcode.redis.cache.initialCacheNamesAndDuration=testCacheMap:15m
code
package com.jgma.xcode.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.lang.Nullable;

import java.io.Serializable;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: admin
 * @GitHub https://github.com/JGMa-java/magic-code.git
 */
@Slf4j
@Configuration
public class RedisConfig {

    @Value("${xcode.redis.cache.initialCacheNamesAndDuration}")
    private String[] initialCacheNames;

    private Pattern pattern = Pattern.compile("(?:([-+]?[0-9]+)M)|(?:([-+]?[0-9]+)H)|(?:([-+]?[0-9]+)S)", Pattern.CASE_INSENSITIVE);

    private String regStr = "m|M|s|S|h|H";

    /**
     * 配置redisTemplate序列化方式,使用默认的序列化manager查看会显示乱码
     */
    @Bean
    public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Serializable> template = new RedisTemplate<>();
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 使用Jackson2JsonRedisSerialize 替换默认的jdkSerializeable序列化redis的value值
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }


    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {

        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);

        Map<String, RedisCacheConfiguration> initialCacheConfigurations = new LinkedHashMap();

        for (String initialCacheName : initialCacheNames) {
            String[] split = initialCacheName.split(":");
            String cacheName = split[0];
            String durationStr = split[1];

            Duration duration = null;
            try {
                duration = parseDuration(durationStr);
            } catch (Exception e) {
                log.error(e.getMessage());
                continue;
            }
            RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(duration);
            initialCacheConfigurations.put(cacheName, cacheConfiguration);
        }
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisCacheWriter).withInitialCacheConfigurations(initialCacheConfigurations).build();

        return redisCacheManager;
    }

    /**
     * 过期时间配置转Duration,仅支持时分秒格式
     *
     * @param duration 需要匹配的配置时间;例 - 2s
     * @return
     * @throws RuntimeException 不支持的时间格式
     */
    private Duration parseDuration(@Nullable String duration) throws RuntimeException {
        Matcher matcher = pattern.matcher(duration);
        if (!matcher.matches()) {
            throw new RuntimeException("[过期时间仅支持h,s,m格式]当前参数:{" + duration + "}");
        }
        if (duration.contains("m") || duration.contains("M")) {
            return Duration.ofMinutes(Long.valueOf(duration.replaceAll(regStr, "")));
        } else if (duration.contains("s") || duration.contains("S")) {
            return Duration.ofSeconds(Long.valueOf(duration.replaceAll(regStr, "")));
        } else {
            return Duration.ofHours(Long.valueOf(duration.replaceAll(regStr, "")));
        }

    }

}

业务层
package com.jgma.xcode.redis.service;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: admin
 */
@Service
public class RedisService {
    private static Map<String, String> result = new HashMap();

    static {
        result.put("1", "字符串1");
        result.put("2", "字符串2");
    }

    @Cacheable(key = "#key",value = "testCacheMap",cacheManager = "cacheManager")
    public Object get(String key) {
        System.out.println("我是测试cache,service返回的。。。");
        return result.get(key);
    }
}

个人感觉代码不是太优美,有没有好的优化方式???

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值