springboot启动读取数据字典缓存到redis实现方式
作者:Filwaod
文章描述了如何通过增加数据字典表和使用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.往表中插入几条数据
再启动项目,看效果


7.redis中查看
可以看到redis在序列化对象时,把类信息(@class)也序列化进来了,这样存的作用是反序列化时知道反序列化成什么对象,但是浪费了内存空间;不想存类信息的话,需要手动序列化成字符串再存进来,获取时再手动反序列成对象,看你怎么选择了

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://www.jb51.net/program/36014522y.htm

9.使用
//使用 String value = redisService.getDataDictionary(CONTRACT_STATUS, "0"); System.out.println(value);
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
