SpringBoot使用Redis作为缓存器缓存数据的操作步骤以及避坑方案

1.非注解式实现

2.1使用之前要明确使用的业务场景

例如我们在登录时,可以让redis缓存验证码,又如在分类下显示菜品数据时,我们可以对分类和菜品进行缓存数据等等。

2.2导入Redis相关依赖

复制代码
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.3在使用的controller层导入RedisTemplate

例如:

说明一下:这里为什么使用@Resource注解而不使用@Autowired注解。

在Spring框架中,@Resource和@Autowired都是用来完成依赖注入的注解,它们可以将其他组件或者资源注入到当前的类中。在Spring框架中,@Resource和@Autowired都是用来完成依赖注入的注解,它们可以将其他组件或者资源注入到当前的类中

**@Resource是Java提供的一个通用注解,而@Autowired是Spring框架提供的注解。@Resource注解默认按照名称进行装配,通过name属性指定注入的目标对象名称。而@Autowired默认按照类型进行装配,它会自动根据类型选择合适的对象进行注入。**另外,@Autowired注解可以配合@Qualifier注解一起使用,通过指定具体的bean名称来完成注入。

其次,@Resource可以用于注入任意的bean,包括其他类、接口、甚至是字符串等类型的资源而@Autowired注解主要用于注入其他的bean对象

此外,@Resource注解可以标注在字段、setter方法、构造方法和方法上,而@Autowired注解通常标注在字段和构造方法上。

在实践中,选择使用@Resource还是@Autowired取决于具体的需求和场景。如果需要按照名称进行注入,或者需要注入的对象是一个非Spring托管的对象,可以使用@Resource注解。如果只是简单的注入Spring托管的对象,并且希望按照类型自动选择合适的bean进行注入,可以使用@Autowired注解。

需要注意的是,@Resource和@Autowired注解都需要对应的类进行配置,以让Spring框架知道需要进行依赖注入的对象。

通过上面的说明,其实我们自己内心里已经有答案,孰强孰弱啦。

2.4此时,我们要配置Redis

2.4.1配置application.yml

2.4.2编写RedisConfig配置类

由于Redis是一个内存数据库,它将数据存储在内存中,因此需要将数据序列化为字节流进行存储。在将数据存入Redis或从Redis中取出数据时,需要进行序列化和反序列化的操作。

java 复制代码
@Configuration
public class RedisConfig extends CachingConfigurerSupport {


    /**
     * 自定义RedisTemplate
     * 设置Redis序列化方式,默认使用的是JDKSerializer的序列化方式,效率低,所以这里设置使用FastJsonRedisSerializer
     */
    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 设置redis连接(LettuceConnectionFactory实现了RedisConnectionFactory)
        redisTemplate.setConnectionFactory(connectionFactory);

        FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);

        // key设置StringRedisSerializer序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // Hash key设置序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());


        return redisTemplate;
    }

}

可以参考一下,或许有更好的,大家可以借鉴一下。

2.5使用缓存(验证码为例)

此时我们可以测试一下,在此之前呢,怎么看缓存数据是一个问题,所以,安排一下Redis的可视化工具:

链接:https://pan.baidu.com/s/1OUNza9ea9fQepXqNTeTq-g

提取码:frpd

2.6测试

这只是一个简单的应用,然后我们再来一个其他的案例:缓存菜品数据

业务场景如下:

每个分类,比如湘菜,川菜,每次点击都需要再次重新查询数据库,不仅压力更大而且造成资源浪费,我们可以把这些查询的数据,按菜品分类给存入redis中,设置其30分钟生存周期,这样再次点击查看,就不会再查询数据库,直接从redis中获取数据,降低服务器压力也避免资源浪费。

缓存逻辑:

我们先动态构造唯一key值,然后根据key来获取value,接下来判断value是否为空,若不为空则表示redis中有该分类下的数据,直接返回;若为空则需要去数据库查询数据,然后再把查询的数据放入redis缓存中,下次再查询直接走redis缓存,不用再次查询数据库。

这个就不再演示了,到这里我们就可以明显觉得,代码量上来了,这只是一个查询都这样,再细想一下,这个查询会不会因为这个缓存出现问题,比如说我们新增了菜品,修改了菜品,删除了菜品,这个缓存区是不是得动一动,那这个重复的代码多不多,显而易见。

2.使用Spring Cache框架优化Redis缓存的过程

简单介绍一下这一位大咖:Spring Cache框架是Spring框架提供的一套基于注解的缓存解决方案,它在应用程序中简化了缓存操作的管理和使用。

Spring Cache框架的核心思想是通过在方法上添加缓存注解,来实现自动缓存的功能。它提供了一些常用的注解,如:

  • @Cacheable:标注在方法上,表示该方法的返回结果可以被缓存,当方法被调用时,会首先检查缓存,如果缓存命中,则直接返回缓存中的结果,不再执行方法体中的逻辑。
  • @CachePut:标注在方法上,表示该方法的返回结果需要更新缓存,每次方法被调用后,都会将返回结果更新到缓存中。
  • @CacheEvict:标注在方法上,表示该方法会清除缓存中的数据,可以用于在更新或删除数据时清除相应的缓存。

2.1导入Spring Cache依赖

复制代码
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>

2.2启动类上加上注解开启缓存

2.3返回结果类实现序列化接口

2.4改造上一个案例的代码

不用意外,就是什么关于redis的什么都不剩了 ,我们只需要再控制层的接口上加上一个注解,就完事了。

2.5测试

测试后即会在redis中产生一个这样的目录结构

对照接口上的注解再理解一下你就会明白其中的意思了。

这个时候你和非注解方式对比你会发现一个问题,过期时间去哪啦,没法设置过期时间了!

3.再次优化Spring Cache使用

使用@Cacheable时,无法直接设置过期时间,需要自定义RedisCacheManager来实现ttl设置。

3.1编写TtlRedisCacheManager类来获取注解@Cacheable的参数

java 复制代码
public class TtlRedisCacheManager extends RedisCacheManager {
    public TtlRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        String[] cells = StringUtils.delimitedListToStringArray(name, "=");
        name = cells[0];
        if (cells.length > 1) {
            long ttl = Long.parseLong(cells[1]);
            // 根据传参设置缓存失效时间,默认单位是秒
            cacheConfig = cacheConfig.entryTtl(Duration.ofMinutes(ttl));
        }
        return super.createRedisCache(name, cacheConfig);
    }
}

3.2修改RedisConfig配置类

java 复制代码
@Configuration
public class RedisConfig extends CachingConfigurerSupport {


    /**
     * 自定义RedisTemplate
     * 设置Redis序列化方式,默认使用的是JDKSerializer的序列化方式,效率低,所以这里设置使用FastJsonRedisSerializer
     */
    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 设置redis连接(LettuceConnectionFactory实现了RedisConnectionFactory)
        redisTemplate.setConnectionFactory(connectionFactory);

        FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);

        // key设置StringRedisSerializer序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // Hash key设置序列化
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());


        return redisTemplate;
    }

    /**
     * 实例化自定义的缓存管理器
     */
    @Bean
    @Primary
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
        return new TtlRedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }


}

注意:项目中已配置了RedisCacheManager需要在原配置的bean上添加注解@Primary,以免造成干扰

3.3修改controller层数据接口的注解

根据你在RedisCacheManager中设置的什么格式来填写value即可。

即完成对Redis缓存数据的使用。有什么问题还请留言。

相关推荐
异世界贤狼转生码农1 小时前
MongoDB Windows 系统实战手册:从配置到数据处理入门
数据库·mongodb
QuZhengRong1 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
码农阿豪1 小时前
Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
数据库·windows
时序数据说7 小时前
时序数据库市场前景分析
大数据·数据库·物联网·开源·时序数据库
听雪楼主.10 小时前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)10 小时前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺11 小时前
Java应届生求职八股(2)---Mysql篇
数据库·mysql
HMBBLOVEPDX11 小时前
MySQL的事务日志:
数据库·mysql
weixin_4196583113 小时前
MySQL数据库备份与恢复
数据库·mysql
如白驹过隙13 小时前
cloudflare缓存配置
前端·缓存