A new project has recently been opened. A data dictionary is used in the project. When the list query data is returned, the code needs to be manually converted to name and displayed at the front desk. The project manager said that a unified function can be encapsulated to avoid programmers from writing their own, confusing code and inconsistent styles.
Based on microservice architecture, the data dictionary is obtained through the service;
Simplified code, easy to use;
Use Redis;
The general direction is to customize annotations and perform data processing during serialization; Considering microservices, it is necessary to put the main logic into common, and then provide interfaces to the outside world. Each business service implements the interface to obtain dictionary data; considering Redis, when serializing data, it is first obtained through Redis. If it cannot be obtained, it is obtained through the interface. , after getting the data, store it in Redis, and then return to processing; you can also take an extra step and update the Redis content synchronously when adding or modifying the data dictionary to ensure data validity.
Define annotations
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonSerialize(using = DictSerializer.class) public @interface Dict { /** 字典类型 */ String type(); }
Specify the location to add annotations
Specify the annotation effective time
Specify the serialization processing class
Serialization processing class
public class DictSerializer extends StdSerializer<Object> implements ContextualSerializer { /** 字典注解 */ private Dict dict; public DictSerializer() { super(Object.class); } public DictSerializer(Dict dict) { super(Object.class); this.dict = dict; } private String type; @Override public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (Objects.isNull(value)) { gen.writeObject(value); return; } if (Objects.nonNull(dict)){ type = dict.type(); } // 通过数据字典类型和value获取name gen.writeObject(value); gen.writeFieldName(gen.getOutputContext().getCurrentName()+"Name"); gen.writeObject(label); } @Override public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty beanProperty) throws JsonMappingException { if (Objects.isNull(beanProperty)){ return prov.findValueSerializer(beanProperty.getType(), beanProperty); } Dict dict = beanProperty.getAnnotation(Dict.class); if (Objects.nonNull(dict)){ type = dict.type(); return this; } return prov.findNullValueSerializer(null); } }
The logic processed here is that the original field content remains unchanged, and a new field is added to store the converted value;
data Dictionary acquisition
private static String changeLabel(String type,String code) { if(code.indexOf(",") > -1) { String[] strs = code.split(","); if (strs.length > 1) { StringBuilder sb = new StringBuilder(); for (String str : strs) { // 从缓存中获取字典。如果不行,通过SpringUtil.getBean(); 获取服务处理 sb.append(DictDataCache.getLabel(type, str)).append(separator); } return sb.substring(0, sb.length() - 1); } } // 从缓存中获取字典。如果不行,通过SpringUtil.getBean(); 获取服务处理 return DictDataCache.getLabel(type, code); }
Consider the situation of multiple selection, first determine whether it is multiple selection, default comma splicing, add input parameter control later;
@Override public String getDictDataOptions(String typeCode,String value) { if (redisTemplate.hasKey("dict:"+typeCode+":"+value)){ return (String) redisTemplate.opsForValue().get("dict:"+typeCode+":"+value); } List<DictDataOptions> dictDataList = getDictDataHandler().getDictDataOptions(typeCode); if(CollUtil.isNotEmpty(dictDataList)) { put(typeCode, dictDataList); } if (redisTemplate.hasKey("dict:"+typeCode+":"+value)){ return (String) redisTemplate.opsForValue().get("dict:"+typeCode+":"+value); } return null; }
According to key Determine whether it exists in Redis. If it exists, get it directly. If it does not exist, get it through the interface. If you get it, put it directly into Redis, and then get it from Redis again.
protected void put(String typeCode, List<DictDataOptions> dataList) { if (CollUtil.isNotEmpty(dataList)){ for (DictDataOptions dictDataOptions : dataList) { AbstractDictHandler.redisTemplate.opsForValue().set("dict:"+typeCode+":"+dictDataOptions.getDataLabel(),dictDataOptions.getDataValue()); } } }
Placing data dictionary values in a loop
@Override public List<DictDataOptions> getDictDataOptions(String typeCode) { return iSysDictService.queryDictItemsByCode(typeCode).stream() .map(e -> DictDataOptions.builder().typeCode(typeCode).dataLabel(e.getValue()).dataValue(e.getText()).build()) .collect(Collectors.toList()); }
According to the data dictionary type, obtain data through the interface; note that this implementation class requires one implementation for each microservice; and then in order to avoid the basic data service from hanging, If an error is reported when calling, a default implementation is provided in common.
4. Use
@Dict(type = "inspectType") private String checkType;
to add annotations to the corresponding fields in the entity returned to the front end, and specify the data dictionary type value
{ "id": "1522492702905954306", "professionName": "专业名称888", "checkCode": "检测项编码8", "checkProject": "rrrr检测项目88", "checkDevice": "52", "checkStandard": "检测项编码88", "referenceStandard": "wq参考标准8", "checkType": "1", "checkTypeName": "尺寸", "remarks": "ef备注备注8" },
The json obtained by the front end will have one more field: checkTypeName, the content is the Chinese value of checkType.
The above is the detailed content of How to get the data dictionary based on an annotation in Springboot. For more information, please follow other related articles on the PHP Chinese website!