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;
    }
相关推荐
陈文锦丫21 小时前
MQ的学习
java·开发语言
乌暮21 小时前
JavaEE初阶---线程安全问题
java·java-ee
爱笑的眼睛1121 小时前
GraphQL:从数据查询到应用架构的范式演进
java·人工智能·python·ai
Seven971 天前
剑指offer-52、正则表达式匹配
java
代码or搬砖1 天前
RBAC(权限认证)小例子
java·数据库·spring boot
青蛙大侠公主1 天前
Thread及其相关类
java·开发语言
Coder_Boy_1 天前
DDD从0到企业级:迭代式学习 (共17章)之 四
java·人工智能·驱动开发·学习
2301_768350231 天前
MySQL为什么选择InnoDB作为存储引擎
java·数据库·mysql
派大鑫wink1 天前
【Java 学习日记】开篇:以日记为舟,渡 Java 进阶之海
java·笔记·程序人生·学习方法