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;
    }
相关推荐
chxii11 分钟前
5java集合框架
java·开发语言
weixin_5450193239 分钟前
微信小程序智能商城系统(uniapp+Springboot后端+vue管理端)
spring boot·微信小程序·uni-app
yychen_java1 小时前
R-tree详解
java·算法·r-tree
搞不懂语言的程序员2 小时前
Redis的Pipeline和Lua脚本适用场景是什么?使用时需要注意什么?
数据库·redis·lua
JANYI20182 小时前
嵌入式设计模式基础--C语言的继承封装与多态
java·c语言·设计模式
xrkhy2 小时前
反射, 注解, 动态代理
java
Ten peaches2 小时前
Selenium-Java版(操作元素)
java·selenium·测试工具·html
一只码代码的章鱼2 小时前
Spring的 @Validate注解详细分析
前端·spring boot·算法
lyw2056192 小时前
RabbitMQ,Kafka八股(自用笔记)
java
邹诗钰-电子信息工程2 小时前
嵌入式自学第二十一天(5.14)
java·开发语言·算法