zoukankan      html  css  js  c++  java
  • 基于springboot2.x集成缓存注解及设置过期时间

    添加以下配置信息;

    /**
     * 基于注解添加缓存
     */
    @Configuration
    @EnableCaching
    public class CacheConfig extends CachingConfigurerSupport {
    
        private final RedisConnectionFactory redisConnectionFactory;
    
        CacheConfig(RedisConnectionFactory redisConnectionFactory) {
            this.redisConnectionFactory = redisConnectionFactory;
        }
    
        @Bean
        @Override
        public KeyGenerator keyGenerator() {
            return (o, method, objects) -> {
                StringBuilder sb = new StringBuilder(32);
                sb.append(o.getClass().getSimpleName());
                sb.append(".");
                sb.append(method.getName());
                if (objects.length > 0) {
                    sb.append("#");
                }
                String sp = "";
                for (Object object : objects) {
                    sb.append(sp);
                    if (object == null) {
                        sb.append("NULL");
                    } else {
                        sb.append(object.toString());
                    }
                    sp = ".";
                }
                return sb.toString();
            };
        }
    
        /**
         * 配置 RedisCacheManager,使用 cache 注解管理 redis 缓存
         */
        @Bean
        @Override
        public CacheManager cacheManager() {
            // 初始化一个RedisCacheWriter
            RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
    
            // 设置默认过期时间:30 分钟
            RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofMinutes(30))
                    // .disableCachingNullValues()
                    // 使用注解时的序列化、反序列化
                    .serializeKeysWith(MyRedisCacheManager.STRING_PAIR)
                    .serializeValuesWith(MyRedisCacheManager.FASTJSON_PAIR);
    
            return new MyRedisCacheManager(cacheWriter, defaultCacheConfig);
        }
    }
    

    redis配置信息:

    @Configuration
    @ConditionalOnClass(RedisOperations.class)
    @EnableConfigurationProperties(RedisProperties.class)
    @Import({LettuceConnectionConfiguration.class})
    public class RedisConfig {
    
        @Bean
        @ConditionalOnMissingBean(name = "redisTemplate")
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            RedisTemplate<Object, Object> template = new RedisTemplate<>();
            // set key serializer
            StringRedisSerializer serializer = MyRedisCacheManager.STRING_SERIALIZER;
            // 设置key序列化类,否则key前面会多了一些乱码
            template.setKeySerializer(serializer);
            template.setHashKeySerializer(serializer);
    
            // fastjson serializer
            GenericFastJsonRedisSerializer fastSerializer = MyRedisCacheManager.FASTJSON_SERIALIZER;
            template.setValueSerializer(fastSerializer);
            template.setHashValueSerializer(fastSerializer);
            // 如果 KeySerializer 或者 ValueSerializer 没有配置,则对应的 KeySerializer、ValueSerializer 才使用这个 Serializer
            template.setDefaultSerializer(fastSerializer);
    
            // factory
            template.setConnectionFactory(redisConnectionFactory);
            template.afterPropertiesSet();
            return template;
        }
    
    
        @Bean
        @ConditionalOnMissingBean
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    
    }
    

    重写RedisCacheManager

    public class MyRedisCacheManager extends RedisCacheManager implements ApplicationContextAware, InitializingBean {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(MyRedisCacheManager.class);
    
        private ApplicationContext applicationContext;
    
        private Map<String, RedisCacheConfiguration> initialCacheConfiguration = new LinkedHashMap<>();
    
        /**
         * key serializer
         */
        public static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer();
    
        /**
         * value serializer
         * <pre>
         *     使用 FastJsonRedisSerializer 会报错:java.lang.ClassCastException
         *     FastJsonRedisSerializer<Object> fastSerializer = new FastJsonRedisSerializer<>(Object.class);
         * </pre>
         */
    
        public static final GenericFastJsonRedisSerializer FASTJSON_SERIALIZER = new GenericFastJsonRedisSerializer();
    
        /**
         * key serializer pair
         */
        public static final RedisSerializationContext.SerializationPair<String> STRING_PAIR = RedisSerializationContext
                .SerializationPair.fromSerializer(STRING_SERIALIZER);
        /**
         * value serializer pair
         */
        public static final RedisSerializationContext.SerializationPair<Object> FASTJSON_PAIR = RedisSerializationContext
                .SerializationPair.fromSerializer(FASTJSON_SERIALIZER);
    
        public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
            super(cacheWriter, defaultCacheConfiguration);
        }
    
        @Override
        public Cache getCache(String name) {
            Cache cache = super.getCache(name);
            return new RedisCacheWrapper(cache);
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public void afterPropertiesSet() {
            String[] beanNames = applicationContext.getBeanNamesForType(Object.class);
            for (String beanName : beanNames) {
                final Class clazz = applicationContext.getType(beanName);
                add(clazz);
            }
            super.afterPropertiesSet();
        }
    
        @Override
        protected Collection<RedisCache> loadCaches() {
            List<RedisCache> caches = new LinkedList<>();
            for (Map.Entry<String, RedisCacheConfiguration> entry : initialCacheConfiguration.entrySet()) {
                caches.add(super.createRedisCache(entry.getKey(), entry.getValue()));
            }
            return caches;
        }
    
        private void add(final Class clazz) {
            ReflectionUtils.doWithMethods(clazz, method -> {
                ReflectionUtils.makeAccessible(method);
                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;
                }
                Caching caching = AnnotationUtils.findAnnotation(method, Caching.class);
                if (caching != null) {
                    Cacheable[] cs = caching.cacheable();
                    if (cs.length > 0) {
                        for (Cacheable c : cs) {
                            if (cacheExpire != null && c != null) {
                                add(c.cacheNames(), cacheExpire);
                            }
                        }
                    }
                } else {
                    CacheConfig cacheConfig = AnnotationUtils.findAnnotation(clazz, CacheConfig.class);
                    if (cacheConfig != null) {
                        add(cacheConfig.cacheNames(), cacheExpire);
                    }
                }
            }, method -> null != AnnotationUtils.findAnnotation(method, CacheExpire.class));
        }
    
        private void add(String[] cacheNames, CacheExpire cacheExpire) {
            for (String cacheName : cacheNames) {
                if (cacheName == null || "".equals(cacheName.trim())) {
                    continue;
                }
                long expire = cacheExpire.expire();
                LOGGER.info("cacheName: {}, expire: {}", cacheName, expire);
                if (expire >= 0) {
                    // 缓存配置
                    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                            .entryTtl(Duration.ofSeconds(expire))
                            .disableCachingNullValues()
                            // .prefixKeysWith(cacheName)
                            .serializeKeysWith(STRING_PAIR)
                            .serializeValuesWith(FASTJSON_PAIR);
                    initialCacheConfiguration.put(cacheName, config);
                } else {
                    LOGGER.warn("{} use default expiration.", cacheName);
                }
            }
        }
    
        protected static class RedisCacheWrapper implements Cache {
            private final Cache cache;
    
            RedisCacheWrapper(Cache cache) {
                this.cache = cache;
            }
    
            @Override
            public String getName() {
                // LOGGER.info("name: {}", cache.getName());
                try {
                    return cache.getName();
                } catch (Exception e) {
                    LOGGER.error("getName ---> errmsg: {}", e.getMessage(), e);
                    return null;
                }
            }
    
            @Override
            public Object getNativeCache() {
                // LOGGER.info("nativeCache: {}", cache.getNativeCache());
                try {
                    return cache.getNativeCache();
                } catch (Exception e) {
                    LOGGER.error("getNativeCache ---> errmsg: {}", e.getMessage(), e);
                    return null;
                }
            }
    
            @Override
            public ValueWrapper get(Object o) {
                // LOGGER.info("get ---> o: {}", o);
                try {
                    return cache.get(o);
                } catch (Exception e) {
                    LOGGER.error("get ---> o: {}, errmsg: {}", o, e.getMessage(), e);
                    return null;
                }
            }
    
            @Override
            public <T> T get(Object o, Class<T> aClass) {
                // LOGGER.info("get ---> o: {}, clazz: {}", o, aClass);
                try {
                    return cache.get(o, aClass);
                } catch (Exception e) {
                    LOGGER.error("get ---> o: {}, clazz: {}, errmsg: {}", o, aClass, e.getMessage(), e);
                    return null;
                }
            }
    
    
            @Override
            public <T> T get(Object o, Callable<T> callable) {
                // LOGGER.info("get ---> o: {}", o);
                try {
                    return cache.get(o, callable);
                } catch (Exception e) {
                    LOGGER.error("get ---> o: {}, errmsg: {}", o, e.getMessage(), e);
                    return null;
                }
            }
    
            @Override
            public void put(Object o, Object o1) {
                // LOGGER.info("put ---> o: {}, o1: {}", o, o1);
                try {
                    cache.put(o, o1);
                } catch (Exception e) {
                    LOGGER.error("put ---> o: {}, o1: {}, errmsg: {}", o, o1, e.getMessage(), e);
                }
            }
    
            @Override
            public ValueWrapper putIfAbsent(Object o, Object o1) {
                // LOGGER.info("putIfAbsent ---> o: {}, o1: {}", o, o1);
                try {
                    return cache.putIfAbsent(o, o1);
                } catch (Exception e) {
                    LOGGER.error("putIfAbsent ---> o: {}, o1: {}, errmsg: {}", o, o1, e.getMessage(), e);
                    return null;
                }
            }
    
            @Override
            public void evict(Object o) {
                // LOGGER.info("evict ---> o: {}", o);
                try {
                    cache.evict(o);
                } catch (Exception e) {
                    LOGGER.error("evict ---> o: {}, errmsg: {}", o, e.getMessage(), e);
                }
            }
    
            @Override
            public void clear() {
                // LOGGER.info("clear");
                try {
                    cache.clear();
                } catch (Exception e) {
                    LOGGER.error("clear ---> errmsg: {}", e.getMessage(), e);
                }
            }
        }
    }
    

    应用:

    @GetMapping("/getShopByShopNO/{shopNo}")
    public Mono<ShopDO> getShopByShopNO(@PathVariable("shopNo") final String shopNo){
        final ShopDO shopByShopNO = shopDAO.getShopByShopNO(shopNo);
        return Mono.just(shopByShopNO);
    }
    
    /**
     * 查询店铺详情
     * @param shopNo
     * @return
    */
    @Cacheable(value = "shop",key = "'shop_'.concat(#root.args[0])",sync = true)
    @CacheExpire(30)
    ShopDO getShopByShopNO(String shopNo);
    

    参考:https://www.cnblogs.com/wjwen/p/9301119.html

  • 相关阅读:
    C语言实现时间差、星期、天数算日期(转)
    windbg 源码调试设置
    Windbg调试命令详解
    突破session 0隔离 和 劫持exe注入(转自梦无极)
    debug : StartService failed, getlasterror = 0x7f(127) 转
    反调试技巧总结-原理和实现
    关于Win7 x64下过TP保护(内核层)(转)
    python将dict中的unicode打印成中文
    Python 获取接口数据,解析JSON,写入文件
    python提取网页中json数据
  • 原文地址:https://www.cnblogs.com/hujinshui/p/11341564.html
Copyright © 2011-2022 走看看