16. 尚融宝后台引入Redis存储数据字典

一、简介

1、场景

由于数据字典的变化不是很频繁,而且系统对数据字典的访问较频繁,所以我们有必要把数据字典的数据存入缓存,减少数据库压力和提高访问速度。这里,我们使用Redis作为系统的分布式缓存中间件。

2、RedisTemplate

在Spring Boot项目中中,默认集成Spring Data Redis,Spring Data Redis针对Redis提供了非常方便的操作模版RedisTemplate,并且可以进行连接池自动管理。

二、引入Redis

1、项目中集成Redis

service-base模块中添加redis依赖,Spring Boot 2.0以上默认通过commons-pool2连接池连接Redis

		<!-- 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>

2、添加Redis连接配置

service-core 模块的 application.yml 中添加如下配置

#spring: 
  redis:
    host: 192.168.2.190
    port: 6379
    database: 0
    #password: 123456 # 密码为空,不需要加这个字段
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0

在这里插入图片描述

3、启动Redis服务

远程连接Linux服务器

# 普通方式
cd /usr/local/redis-5.0.8
bin/redis-server redis.conf

# docker方式
docker run -d -p 6379:6379 --name myredis redis:5.0.8

三、测试RedisTemplate

1、存值测试

service-core模块

test目录下创建测试类

RedisTemplateTests.java

package com.indi.srb.core;

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTemplateTests {
    @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,不易于使用,需要添加序列化配置。

2、Redis配置文件

service-base 模块config包下

创建RedisConfig.java,在这个配置文件中配置Redis序列化方案

package com.indi.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);

        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型
        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;
    }
}

再次测试,key使用了字符串存储,value使用了json存储

3、取值测试

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

四、将数据字典存入Redis

当redis服务器宕机时,不要抛出异常,要正常的执行后面的流程,使业务可以正常的运行

service-core模块service.impl包下

修改DictServiceImpl.java

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public List<Dict> listByParentId(Long parentId) {
        List<Dict> dictList = null;
        try {
            dictList = (List<Dict>) redisTemplate.opsForValue().get("srb:core:dictList:" + parentId);
            if (dictList != null) {
                log.info("来自redis的数据");
                return dictList;
            }
        } catch (Exception e) {
            log.error("读取redis失败:" + ExceptionUtils.getStackTrace(e));
        }

        log.info("从数据库查询数据");
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<Dict>().eq("parent_id", parentId);
        dictList = baseMapper.selectList(queryWrapper);
        dictList.forEach(dict -> {
            dict.setHasChildren(this.hasChildren(dict.getId()));
        });

        try {
            redisTemplate.opsForValue().set("srb:core:dictList:" + parentId, dictList, 5, TimeUnit.MINUTES);
            log.info("存入redis成功");
        } catch (Exception e) {
            log.error("存入redis失败:" + ExceptionUtils.getStackTrace(e));
        }
        return dictList;
    }

在这里插入图片描述

在这里插入图片描述

五、测试

第一次,刚进入数据字典

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进入二级菜单

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第二次,刷新页面,重新进入字典,直接走redis缓存了
在这里插入图片描述
再进入二级菜单,也是直接走缓存,测试成功!
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值