spring boot 2.2.1 配置 redis 缓存

作者: gimmi7 | 来源:发表于2019-11-16 19:24 被阅读0次

    pom文件添加如下依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.62</version>
            </dependency>
    

    配置appliation.yml文件

    我这里配置的是集群,单机就配置host,port

    spring:
      redis:
        lettuce:
          pool:
            max-active: 1000
            max-wait: -1
            max-idle: 10
            min-idle: 2
        timeout: 2000
        cluster:
          nodes:
            - 192.168.5.244:7000
    

    配置CacheManager以及KeyGenerator

    package com.rstim.user.cache.config;
    ...
    @Configuration
    @EnableCaching
    @Slf4j
    public class RedisCacheConfig extends CachingConfigurerSupport {
    
        @Bean
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<Object, Object> template = new RedisTemplate<>();
            template.setConnectionFactory(factory);
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new GenericFastJsonRedisSerializer());
            template.afterPropertiesSet();
            return template;
        }
    
        /**
         * redis缓存管理器
         */
        @Bean
        @Primary
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                    .cacheDefaults(this.cacheConfiguration(Duration.ofHours(6)))
                    .withInitialCacheConfigurations(this.cacheConfigurationMap())
                    .build();
            return cacheManager;
        }
    
        /**
         * redis缓存管理器配置列表;
         * 可以根据业务需要配置不同的过期时间;
         */
        private Map<String, RedisCacheConfiguration> cacheConfigurationMap() {
            Map<String, RedisCacheConfiguration> configurationMap = new HashMap<>();
            configurationMap.put("m5", this.cacheConfiguration(Duration.ofMinutes(5)));
            return configurationMap;
        }
    
    
        /**
         * redis缓存管理器的默认配置;
         * 使用fastJson序列化value,model不再需要实现Serializable接口;
         *
         * @param ttl 设置默认的过期时间,防止 redis 内存泄漏
         */
        private RedisCacheConfiguration cacheConfiguration(Duration ttl) {
            RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
            configuration = configuration
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()))
                    .entryTtl(ttl);
            return configuration;
        }
    
    
        /**
         * 通用redis缓存key生成策略
         */
        @Bean
        @Override
        public KeyGenerator keyGenerator() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    StringBuffer sb = new StringBuffer();
                    sb.append(target.getClass().getName());
                    for (Object obj : params) {
                        sb.append(CacheKeyUtil.getCacheKey(obj));
                    }
                    log.info("cacheKey={}", sb.toString());
                    return sb.toString();
                }
            };
        }
    
    
    }
    
    

    自己写了一个工具类CacheKeyUtil,通过反射获取redis缓存key的后缀

    主要用于解决更新缓存的场景时通常会传入pojo类,

    而获取数据时通过传入id参数

    package com.rstim.user.cache.utils;
    
    
    import lombok.extern.slf4j.Slf4j;
    
    import java.lang.reflect.Method;
    
    @Slf4j
    public class CacheKeyUtil {
    
        public static String getCacheKey(Object obj) {
            if (obj == null) {
                return "null";
            }
            Class clazz = obj.getClass();
            if (clazz.equals(String.class) ||
                    clazz.equals(Integer.class) ||
                    clazz.equals(Long.class) ||
                    clazz.equals(Float.class) ||
                    clazz.equals(Double.class) ||
                    clazz.equals(Boolean.class) ||
                    clazz.equals(Character.class) ||
                    clazz.equals(Byte.class) ||
                    clazz.equals(Short.class)
            ) {
                return obj.toString();
            }
    
            try {
                Method method = clazz.getDeclaredMethod("cacheKey");
                return (String) method.invoke(obj);
            } catch (Exception e) {
                log.warn("invoke cacheKey method fail, use default toString as cacheKey:", e);
                return obj.toString();
            }
        }
    }
    
    使用时只需要在mysql表对应的java对象下实现一个如下方法:
    public String cacheKey() {
            return String.valueOf("这里根据业务添加redis缓存key的后缀,比如user的uuid");
        }
    
    更好的做法是定义一个CacheEntity接口:
    package com.rstim.user.model.cache;
    public interface CacheEntity {
        /**
         * 缓存的实体类实现本接口的cacheKey方法,可以指定缓存时 redis key的唯一后缀
         */
        String cacheKey();
    }
    
    然后让需要进行缓存的java对象去实现CacheEntity接口
    
    

    最后就可以通过 @Cacheable, @CachePut, @CacheEvit 实现redis缓存

    package com.rstim.user.cache.service;
    ...
    @Service
    @CacheConfig(cacheNames = "userInfo")
    public class UserInfoCacheService {
    
        @Autowired
        private UserInfoMapper userInfoMapper;
    
        @CachePut
        public UserInfo updateUserInfo(UserInfo userInfo) {
            userInfoMapper.updateUserInfo(userInfo);
            UserInfo updatedUser =userInfo;// userInfoMapper.selectById(userInfo.getUuid());
            System.out.println("did not go cache");
            return updatedUser;
        }
    
        @Cacheable
        public UserInfo selectById(long uuid) {
            UserInfo userInfo = new UserInfo(uuid);
            System.out.println("did not go cache");
    
            return userInfo;
        }
    
        @CacheEvict
        public void deleteById(long uuid){
            //delete from mysql;
        }
    
    }
    
    

    小提示

    1. 只有被对象或者接口外部方法调用时,spring cache才会发生作用;
    2. 只有加在public方法上的注解,才会让 spring cache生效;
    因为spring cache模式是使用java的动态代理来实现切面缓存,所以有上面两点限制,
    如果想要在对象内部使spring cache生效,可以配置使用cglib来实现代理,具体
    方法可以google.
    

    相关文章

      网友评论

        本文标题:spring boot 2.2.1 配置 redis 缓存

        本文链接:https://www.haomeiwen.com/subject/votuictx.html