首頁  >  文章  >  Java  >  基於Springboot一個註解如何搞定資料字典

基於Springboot一個註解如何搞定資料字典

WBOY
WBOY轉載
2023-05-25 22:58:142601瀏覽

問題引出:

最近開了新項目,項目中用到了資料字典,列表查詢資料回傳的時候需要手動將code轉換為name,到前台展示。專案經理表示可以封裝一個統一的功能,避免程式設計師各自寫各自的,程式碼混亂,風格不統一。

要求:

  • 基於微服務架構,資料字典透過服務取得;

  • ##簡化程式碼,使用簡單;

  • 使用Redis;

方案

#大致的方向是自訂註解,在序列化的時候進行資料處理;考慮到微服務,需要將主要邏輯放到common中,然後對外提供接口,各業務服務實現接口以獲取字典數據; 考慮Redis,序列化處理數據時,首先通過Redis獲取,獲取不到在通過接口獲取,拿到資料後存到Redis中,然後再回傳處理; 也可以多做一步,在新增、修改資料字典時,同步更新Redis內容,以確保資料有效性。

實作

  • 定義註解

  • #
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotationsInside
    @JsonSerialize(using = DictSerializer.class)
    public @interface Dict {
    
        /** 字典类型 */
        String type();
    }
  • 指定註解新增位置

  • 指定註解生效時間

  • 指定序列化處理類別

  • 序列化處理類別

  • 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);
        }
    }
這裡處理的邏輯是原先的欄位內容不變,新增一個新的欄位用來儲存轉換後的值;

    ##數據字典取得
  • 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);
    }
  • 考慮存在多選的情況,先判斷下是否是多選的,預設逗號拼接,後期加入入參控制;
@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;
}

根據key判斷Redis中是否存在,存在則直接獲取,不存在則透過介面獲取,取得到直接放到Redis中,然後再從Redis取得。

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());
        }
    }
}

循環放置資料字典值

@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());
}

根據資料字典類型,透過介面取得資料;注意該實作類別需要每個微服務實作一個;然後為了避免基礎資料服務掛掉,呼叫報錯,common中提供一個預設實作。

4.使用

@Dict(type = "inspectType")
private String checkType;

在傳回前端的實體中,對應欄位加入註解,並指定資料字典type值

      {
        "id": "1522492702905954306",
        "professionName": "专业名称888",
        "checkCode": "检测项编码8",
        "checkProject": "rrrr检测项目88",
        "checkDevice": "52",
        "checkStandard": "检测项编码88",
        "referenceStandard": "wq参考标准8",
        "checkType": "1",
        "checkTypeName": "尺寸",
        "remarks": "ef备注备注8"
      },

前端取得的json會多一個欄位: checkTypeName,內容為checkType 的中文值。

以上是基於Springboot一個註解如何搞定資料字典的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除