Redis在SpringBoot中的使用

在SpringBoot项目中使用redis存储数据作为字典

本项目使用jdk1.8

一、添加依赖

复制代码
<!-- spring boot redis缓存引入 -->
<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>

<!-- redis 存储 json序列化 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

二、配置yml

复制代码
#spring: 
  redis:
    host: 公网IP
    port: 6379
    database: 0
    password: (redis密码) #默认为空
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0

三、写配置类

3.1 为什么写配置类

如果不写配置类,那么往redis存值,会存jdk序列化的数据,无法正常观看数据

3.2 配置类

java 复制代码
package com.atguigu.srb.base.config;

@Configuration
public class RedisConfig {


    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //首先解决key的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);

        //解决value的序列化方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型
        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);


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

四、测试

4.1 存值

java 复制代码
/**
 * FileName: RedisTemplateTest
 * Author: ccy
 * Description:redis测试
 * Date:   2025/4/21 22:23
 */
@SpringBootTest(classes = ServiceCoreApplication.class)
@RunWith(SpringRunner.class)
public class RedisTemplateTest {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private DictMapper dictMapper;

    @Test
    public void saveDict() {
        Dict dict = dictMapper.selectById(1);
        //向数据库中存储string类型的键值对,过期时间5分钟
        redisTemplate.opsForValue().set("dict", dict, 5 , TimeUnit.MINUTES);
    }

}

发现RedisTemplate默认使用了JDK的序列化方式存储了key和value

4.2 取值

java 复制代码
package com.atguigu.srb;

/**
 * FileName: RedisTemplateTest
 * Author: ccy
 * Description:redis测试
 * Date:   2025/4/21 22:23
 */
@SpringBootTest(classes = ServiceCoreApplication.class)
@RunWith(SpringRunner.class)//
public class RedisTemplateTest {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private DictMapper dictMapper;


    @Test
    public void getDict() {
        Dict dict = (Dict)redisTemplate.opsForValue().get("dict");
        System.out.println(dict);

    }

}

五、将数据字典存入Redis

本项目功能实际应用于尚融宝项目

java 复制代码
 // ---------Controller---------

    /**
     * 延迟加载
     * @param parentId 前台传后台参数
     * @return R
     */
    @ApiOperation("根据上级id获取子节点数据列表")
    @GetMapping("/listByParentId/{parentId}")
    public R listByParentId(@ApiParam(value = "上级节点id", required = true)
                                @PathVariable Long parentId) {
        List<Dict> dictList = dictService.listByParentId(parentId);
        return R.ok().data("list", dictList);
    }

// --------ServiceImpl-----------

@Override
    public List<Dict> listByParentId(Long parentId) {

        //用try-catch的原因是redis调用可能出错
        try {

            //首先查询redis中是否存在数据列表
            List<Dict> dictList = (List<Dict>)         redisTemplate.opsForValue().get("srb:core:dictList" + parentId);

            //如果存在,则从redis中直接返回数据列表
            if (dictList != null) {
                log.info("从redis中获取数据列表");
                return dictList;
            }

        } catch (Exception e) {
            //ExceptionUtils.getStackTrace(e): 拿到e对象错误跟踪栈字符串
            log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));
        }

        // 如果不存在,则从数据库中查询,并把数据保存到redis中
        log.info("从数据库中获取数据列表");
        LambdaQueryWrapper<Dict> qW = Wrappers.lambdaQuery();
        qW.eq(Dict::getParentId, parentId);
        List<Dict> dictList = this.list(qW);
        //填充hashChildren字段
        dictList.forEach(dict -> {
            //判断当前节点是否有子节点,找到当前的dict下级是否有子节点
            boolean hasChildren = this.hasChildren(dict.getId());
            dict.setHasChildren(hasChildren);
        });

        try {
            //将数据存入redis
            log.info("将数据存入redis");
            redisTemplate.opsForValue().set("srb:core:dictList" + parentId, dictList, 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));
        }

        //返回数据列表
        return dictList;
    }
相关推荐
皮皮林5517 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
卡尔特斯11 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
白鲸开源11 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
ytadpole11 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫12 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
JavaGuide12 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613512 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源13 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Java中文社群13 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心13 小时前
从零开始学Flink:数据源
java·大数据·后端·flink