springboot启动读取数据字典缓存到redis

因数据库中存的都是数字(数据字典),但是又没有数据字典表,只有后端知道是什么意思,查询返回给前端时,需要if-else进行转换成具体的值,很麻烦,现增加数据字典表,通过redis获取,转换成具体的值

1.建表

CREATE TABLE `data_dictionary`  (
  `id` bigint(20) NOT NULL COMMENT '主键id',
  `module` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '归属模块',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典名',
  `code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典编码',
  `value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '字典取值',
  `order` int(3) NOT NULL DEFAULT -1 COMMENT '排序',
  `state` tinyint(1) NOT NULL DEFAULT -1 COMMENT '启用状态 0:停用 1:启用',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '数据字典表';

2.mybatisplus生成controller,service,mapper,do等,下面是用到的DO,VO

@Data
@TableName("data_dictionary")
@ApiModel(value="DataDictionaryDO对象", description="数据字典表")
public class DataDictionaryDO implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    @ApiModelProperty(value = "归属模块")
    private String module;

    @ApiModelProperty(value = "字典名")
    private String name;

    @ApiModelProperty(value = "字典编码")
    private String code;

    @ApiModelProperty(value = "字典取值")
    private String value;

    @ApiModelProperty(value = "排序")
    private Integer sort;

    @ApiModelProperty(value = "启用状态 0:停用 1:启用")
    private Integer state;

    @ApiModelProperty(value = "创建时间")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

}

@Data
@ApiModel(value = "DateDictionaryVo对象", description = "数据字典Vo")
@ToString
public class DataDictionaryVo implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "字典编码")
    private String code;

    @ApiModelProperty(value = "字典取值")
    private String value;

    @ApiModelProperty(value = "redis key")
    private String key;

}

3.数据字典常量

/**
 * @description:数据字典常量
 */
public class DataDictionaryConstant {

    /**
     * redis中数据字典key
     */
    public static final String DATA_DICTIONARY_KEY = "dataDictionary";

    /**
     * 合同-执行状态
     */
    public static final String CONTRACT_STATUS = "contract:status";
}

4.redis配置

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

5.实现springboot启动查询数据字典表,将数据缓存到redis中,使用@PostConstruct注解

/**
 * @description:项目启动初始化数据字典到redis
 */
@Slf4j
@Component
public class InitConfig {

    @Autowired
    private DataDictionaryMapper  dataDictionaryMapper;
    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void initDataDictionary() {
        log.info("初始数据字典信息-开始");
        if (Boolean.TRUE.equals(redisTemplate.hasKey(DATA_DICTIONARY_KEY))) {
            redisTemplate.delete(DATA_DICTIONARY_KEY);
        }
        List<DataDictionaryDO> dictionaryDOList = dataDictionaryMapper.selectList(null);
        Map<String, List<DataDictionaryVo>> dataMap = dictionaryDOList.stream().map(obj -> {
            DataDictionaryVo dataDictionaryVo = new DataDictionaryVo();
            dataDictionaryVo.setCode(obj.getCode());
            dataDictionaryVo.setValue(obj.getValue());
            dataDictionaryVo.setKey(obj.getModule() + ":" + obj.getName());
            return dataDictionaryVo;
        }).collect(Collectors.groupingBy(DataDictionaryVo::getKey));
        redisTemplate.opsForHash().putAll(DATA_DICTIONARY_KEY, dataMap);
        log.info("初始数据字典信息-结束");
    }
}

6.往表中插入几条数据,再启动项目,看效果
springboot启动读取数据字典缓存到redis_第1张图片

springboot启动读取数据字典缓存到redis_第2张图片
7.redis中查看,可以看到redis在序列化对象时,把类信息(@class)也序列化进来了,这样存的作用是反序列化时知道反序列化成什么对象,但是浪费了内存空间;不想存类信息的话,需要手动序列化成字符串再存进来,获取时再手动反序列成对象,看你怎么选择了
springboot启动读取数据字典缓存到redis_第3张图片
8.将获取封装成一个工具方法,方便调用

@Service
public class RedisService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 缓存中查数据字典
     * @param key redis key
     * @param code  字典编码
     * @return
     */
    public String getDataDictionary(String key, String code) {
        String value = null;
        if (Boolean.TRUE.equals(redisTemplate.hasKey(DATA_DICTIONARY_KEY))) {
            List<DataDictionaryVo> dataDictionary = (List<DataDictionaryVo>) redisTemplate
                .opsForHash().get(DATA_DICTIONARY_KEY, key);
            if (dataDictionary.size() > 0) {
                value = dataDictionary.stream().filter(obj -> code.equals(obj.getCode()))
                    .findFirst().get().getValue();
            }
        }
        return value != null ? value : "";
    }

}

为什么要这么写Boolean.TRUE.equals(redisTemplate.hasKey(key))
而不是redisTemplate.hasKey(DATA_DICTIONARY_KEY)

这是因为idea提示可能会出现空指针,然后查资料修改成上面的写法
https://blog.csdn.net/qq_40822742/article/details/112291105
springboot启动读取数据字典缓存到redis_第4张图片

9.使用

//使用
String value = redisService.getDataDictionary(CONTRACT_STATUS, "0");
System.out.println(value);

你可能感兴趣的:(redis,其他,spring,boot,缓存,redis)