SpringBoot 配置 Redis 多緩存名(不同緩存名緩存失效時間不同)


import com.google.common.collect.ImmutableMap;
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.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.Map;

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //配置使用FastJson進行序列化和反序列化操作
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        template.afterPropertiesSet();
        //開啟Redis事務
        /**
        * 為何要開啟事務呢?redis本身是單線程執行的one by one 
        * 雖然都是原子性操作,那需要多個原子性的操作才算一個完整的事件呢
        * 譬如 redis get set可能就是一對操作才能保證操作的完整性
        * 譬如記錄訪問數 value 從0開始,在並發情況下多線程會同時查詢到 value 為0 的情況,
        * 此時兩線程都得到value 0 為此都 +1操作 執行結果 value=1,而我們期望的結果至少是2才對
        * 所以需要用事務來解決這一堆操作(get set)
        */
        template.setEnableTransactionSupport(true);
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> template) {
        
        //配置多個緩存名稱 這里我們用個能用的模板  這里有坑點往下看
        RedisCacheConfiguration templateRedisCacheCfg = RedisCacheConfiguration
                .defaultCacheConfig()
                // 設置key為String
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
                // 設置value 為自動轉Json的Object
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
                // 不緩存null
                .disableCachingNullValues();
        //這里對RedisCacheConfiguration不熟悉的可能會有疑問,我們這樣批量templateRedisCacheCfg.entryTtl(Duration.ofMinutes(15))最后不都是同一個引用嗎,過期時間會生效嗎?
        Map<String, RedisCacheConfiguration> expires = ImmutableMap.<String, RedisCacheConfiguration>builder()
                .put("15m", templateRedisCacheCfg.entryTtl(Duration.ofMinutes(15)))
                .put("30m", templateRedisCacheCfg.entryTtl(Duration.ofMinutes(30)))
                .put("60m", templateRedisCacheCfg.entryTtl(Duration.ofMinutes(60)))
                .put("1d", templateRedisCacheCfg.entryTtl(Duration.ofDays(1)))
                .put("30d", templateRedisCacheCfg.entryTtl(Duration.ofDays(30)))
                .put("common-30d", templateRedisCacheCfg.entryTtl(Duration.ofDays(30)))
                .build();

        RedisCacheManager redisCacheManager =
                RedisCacheManager.RedisCacheManagerBuilder
                        // Redis 連接工廠
                        .fromConnectionFactory(template.getConnectionFactory())
                        // 默認緩存配置
                        .cacheDefaults(templateRedisCacheCfg.entryTtl(Duration.ofHours(1)))
                        // 配置同步修改或刪除 put/evict
                        .transactionAware()
                        .initialCacheNames(expires.keySet())
                        .withInitialCacheConfigurations(expires)
                        .build();
        return redisCacheManager;
    }
}

序列化類


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import java.nio.charset.Charset;


public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName,SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullListAsEmpty).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject(str, clazz);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM