为了账号安全,请及时绑定邮箱和手机立即绑定

SpringBoot中使用Redis实现缓存

作者:Joepis 原文链接

Spring Data Redis为我们封装了Redis客户端的各种操作,简化使用。

当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作

当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用

关于RedisTemplate的使用可参考:blog.didispace.com/springbootr…

下面总结使用Redis作为缓存
引入依赖
SpringBoot从1.4版本开始,spring-boot-starter-redis依赖改名了。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>1.5.2.RELEASE</version>
</dependency>

配置文件

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 0
    database: 0
    pool:
      max-active: 8
      max-wait: -1
      max-idle: 8
      min-idle: 0

这样,SpringBoot将会自动配置redis,注入相关bean,我们就可以使用@CacheConfig@Cacheable@CachePut@CacheEvict了。

使用Cache注解时的问题
缓存对象集合中,缓存是以key-value形式保存的。当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator生成key。

public class SimpleKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object target, Method method, Object... params) {
        return generateKey(params);
    }

    /**
     * Generate a key based on the specified parameters.
     */
    public static Object generateKey(Object... params) {
        if (params.length == 0) {
            return SimpleKey.EMPTY;
        }
        if (params.length == 1) {
            Object param = params[0];
            if (param != null && !param.getClass().isArray()) {
                return param;
            }
        }
        return new SimpleKey(params);
    }
}
public SimpleKey(Object... elements) {
        Assert.notNull(elements, "Elements must not be null");
        this.params = new Object[elements.length];
        System.arraycopy(elements, 0, this.params, 0, elements.length);
        this.hashCode = Arrays.deepHashCode(this.params);
    }

查看源码可以发现,它是使用方法参数组合生成的一个key。 此时有一个问题: 如果2个方法,参数是一样的,但执行逻辑不同,那么将会导致执行第二个方法时命中第一个方法的缓存。 解决办法是在@Cacheable注解参数中指定key,或者自己实现一个KeyGenerator,在注解中指定KeyGenerator。 但是如果这样的情况很多,每一个都要指定keyKeyGenerator很麻烦。

Spring同样提供了方案:继承CachingConfigurerSupport并重写keyGenerator()

下面贴出代码:

@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {

    @Autowired
    private JedisConnectionFactory jedisConnectionFactory;

    @Bean
    public RedisTemplate redisTemplate() {
        StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public CacheManager cacheManager() {
        String[] cacheNames = {"app_default", "users", "blogs", "goods", "configs", "info"};
        RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate(), Arrays.asList(cacheNames));
        redisCacheManager.setDefaultExpiration(86400);
        return redisCacheManager;
    }

    @Bean
    public Cache cache() {
        return cacheManager().getCache("app_default");
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, objects) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append("::" + method.getName() + ":");
            for (Object obj : objects) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }
}
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消