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