欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java分析講解序列化與字典功能的序列化

 更新時間:2022年06月08日 11:16:33   作者:java愛好者  
在項目開發(fā)地過程中經常會用到字典存儲某些可配置的值,但相應的也會給開發(fā)帶來復雜度,比如數(shù)據(jù)庫存儲的值為字典值:0,1,2,3這種類型的值,但是前端頁面卻需要展示為 啟動、禁用、刪除 等中文狀態(tài),下面我們來看兩種解決方案

兩種解決方案

  • 前端查詢字典數(shù)據(jù)然后前端轉碼
  • 后端查詢字典值,然后再轉碼返回給前段。

本文及時針對方案2 進行的改進

目標:

在需要返回給前段的字段上添加指定的注解例如:@DictDesc 則根據(jù)該字段定義的值結合注解配置生成 xxxDesc字段并自動賦值為注解屬性值所對應的字典描述;

具體使用的技術涉及到jackson序列化與反序列化,其他JSON工具包也類型的效果;

字典注解定義

/**
 * 字典類型字段自動生成Desc描述字段
 */
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DictDescSerializer.class)
@JsonDeserialize(using = DictDescDeserializer.class)
public @interface DictDesc {
    /**
     * 枚舉類型的class
     * 取值:getValue, getCode, getStatus, name
     * 描述:getDesc
     *
     * @return 字典類型
     */
    Class<? extends Enum<? extends DictEnum>>[] enumType() default {};
    /**
     * 字典類型分組
     *
     * @return 字典類型
     */
    String[] dictType() default {};
    /**
     * 字典轉換失敗時默認值
     *
     * @return String 默認值
     */
    String defaultValue() default "";
    /**
     * 是否拋出異常,默認不拋出異常,返回默認值
     *
     * @return true 轉換失敗則拋出異常,false 異常返回默認值
     */
    boolean throwException() default false;
}

該注解中定義了解析該注解需要序列化器與返序列化器:

@JsonSerialize(using = DictDescSerializer.class)

@JsonDeserialize(using = DictDescDeserializer.class)

字典序列化與返序列化器的實現(xiàn)

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.service.impl.DictDescSerializerUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
/**
 * 字典類型返序列化器
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/5/20 21:08
 */
@Slf4j
@NoArgsConstructor
public class DictDescDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {
    /**
     * 生成序列化字段后綴
     */
    private static final String LABEL_SUFFIX = "Desc";
    /**
     * 參數(shù)類型
     */
    private Class<?> rawClass;
    /**
     * 默認轉換器
     */
    private ConversionService converter;
    /**
     * 設置方法
     */
    private Method writeMethod;
    /**
     * 字典配置信息
     */
    private DictDesc dict;
    public DictDescDeserializer(DictDesc dict, BeanProperty property) {
        this.dict = dict;
        this.rawClass = property.getType().getRawClass();
        this.converter = new DefaultConversionService();
        Class<?> targetClass = property.getMember().getDeclaringClass();
        String writeField = property.getName() + LABEL_SUFFIX;
        PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, writeField);
        this.writeMethod = Objects.isNull(propertyDescriptor) ? null : propertyDescriptor.getWriteMethod();
        if (Objects.isNull(this.writeMethod)) {
            log.info("類:{},字典屬性:{},沒有寫入方法:{},不設置值!", targetClass.getName(), property.getName(), writeField);
        }
    }
    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
        DictDesc dict = property.getAnnotation(DictDesc.class);
        if (dict != null) {
            return new DictDescDeserializer(dict, property);
        }
        return this;
    }
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
        Object result = this.getValue(p.getText());
        this.setDictDesc(result, p.getCurrentName(), p.getCurrentValue());
        return result;
    }
    /**
     * 將數(shù)據(jù)類型轉換為目標類型
     *
     * @param value 字符串值
     * @return 目標類型值
     * @throws IOException
     */
    public Object getValue(String value) throws IOException {
        return converter.convert(value, this.rawClass);
    }
    /**
     * 設置字典會限制
     *
     * @param result       字典value
     * @param currentName  當前屬性名稱
     * @param currentValue 當前對象
     */
    private void setDictDesc(Object result, String currentName, Object currentValue) {
        try {
            if (this.writeMethod != null) {
                writeMethod.invoke(currentValue, DictDescSerializerUtils.getDesc(this.dict, currentName, result));
            }
        } catch (Exception e) {
            log.error("類:{},字典屬性:{},回顯異常:{}", currentValue.getClass(), currentName, e.getMessage(), e);
        }
    }
}
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.service.impl.DictDescSerializerUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
/**
 * 字典序列化器
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/5/20 20:48
 */
@Slf4j
@NoArgsConstructor
public class DictDescSerializer extends JsonSerializer<Object> implements ContextualSerializer {
    /**
     * 生成序列化字段后綴
     */
    private static final String LABEL_SUFFIX = "Desc";
    /**
     * 字典配置信息
     */
    private DictDesc dict;
    /**
     * 構造方法
     *
     * @param dict 字典描述
     */
    public DictDescSerializer(DictDesc dict) {
        this.dict = dict;
    }
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        DictDesc dict = property.getAnnotation(DictDesc.class);
        if (dict != null) {
            return new DictDescSerializer(dict);
        }
        return this;
    }
    /**
     * Method that can be called to ask implementation to serialize
     * values of type this serializer handles.
     *
     * @param value    Value to serialize; can <b>not</b> be null.
     * @param gen      Generator used to output resulting Json content
     * @param provider Provider that can be used to get serializers for
     *                 serializing Objects value contains, if any.
     */
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        provider.defaultSerializeValue(value, gen);
        if (dict != null) {
            String fieldName = gen.getOutputContext().getCurrentName();
            // 添加轉換之后的字段:xxxDesc
            gen.writeStringField(fieldName.concat(LABEL_SUFFIX), DictDescSerializerUtils.getDesc(dict, fieldName, value));
        }
    }
}

字典序列化與反序列工具類

import cn.hutool.extra.spring.SpringUtil;
import com.aimilin.common.core.pojo.system.SysDict;
import com.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.annotation.DictEnum;
import com.aimilin.common.dict.exception.DictException;
import com.aimilin.common.dict.exception.enums.DictExceptionEnum;
import com.aimilin.common.dict.service.SysDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
 * 字典轉換工具類
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/5/20 23:19
 */
@Slf4j
public class DictDescSerializerUtils {
    /**
     * 獲取字典信息
     *
     * @param dict  字典對象
     * @param value 字典值
     * @return
     */
    public static String getDesc(DictDesc dict, String field, Object value) {
        if (ArrayUtils.isEmpty(dict.dictType()) && ArrayUtils.isEmpty(dict.enumType())) {
            throw new DictException(DictExceptionEnum.REQUEST_DICT_TYPE, field);
        }
        try {
            if (value == null) {
                throw new DictException(DictExceptionEnum.REQUEST_NOT_NULL, field);
            }
            if (ArrayUtils.isNotEmpty(dict.enumType())) {
                return getEnumDesc(dict, field, value);
            }
            return getDictDesc(dict, field, value);
        } catch (Exception e) {
            log.error("字典轉換異常, field:{}, enumType:{}, dictType:{}, 值:{}, 異常:{}",
                    field, dict.enumType(), dict.dictType(), value, e.getMessage(), e);
            if (dict.throwException()) {
                throw e instanceof DictException ? (DictException) e : new DictException(DictExceptionEnum.DICT_EXCEPTION, e);
            }
            return dict.defaultValue();
        }
    }
    /**
     * 獲取枚舉類型的描述信息
     *
     * @param dict  字典
     * @param value 值
     * @return 枚舉desc字段
     */
    public static String getEnumDesc(DictDesc dict, String field, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        for (Class<? extends Enum<? extends DictEnum>> dictEnum : dict.enumType()) {
            Method getCode = dictEnum.getMethod("getCode");
            Method getMessage = dictEnum.getMethod("getMessage");
            for (Enum<? extends DictEnum> e : dictEnum.getEnumConstants()) {
                if (value.equals(getCode.invoke(e))) {
                    return Objects.toString(getMessage.invoke(e));
                }
            }
        }
        throw new DictException(DictExceptionEnum.UNKNOWN_ENUM_DICT_VALUE,
                String.format("Field:%s, EnumType: %s, Value: %s", field, Arrays.toString(dict.enumType()), value));
    }
    /**
     * 獲取字典中的值
     *
     * @param dict  字典注解
     * @param value 屬性值
     * @return 字典名稱
     */
    public static String getDictDesc(DictDesc dict, String field, Object value) {
        if (ArrayUtils.isEmpty(dict.dictType())) {
            throw new DictException(DictExceptionEnum.REQUEST_DICT_TYPE, field);
        }
        List<SysDict> sysDictList = SpringUtil.getBean(SysDictService.class).getDictByDictTypeCode(dict.dictType());
        if (CollectionUtils.isEmpty(sysDictList)) {
            throw new DictException(DictExceptionEnum.NO_DICT_DATA, field, Arrays.toString(dict.dictType()));
        }
        for (SysDict sysDict : sysDictList) {
            if (StringUtils.equals(sysDict.getCode(), Objects.toString(value))) {
                return sysDict.getValue();
            }
        }
        throw new DictException(DictExceptionEnum.UNKNOWN_DICT_VALUE, field, Arrays.toString(dict.dictType()));
    }
}

字典轉換服務類

/**
 * 字典服務類
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/5/20 16:03
 */
public interface SysDictService {
    /**
     * 根據(jù)字典類型code獲取字典列表
     *
     * @param dictTypeCodes 字典類型code
     * @return List<SysDict>
     */
    public List<SysDict> getDictByDictTypeCode(String... dictTypeCodes);
}

服務實現(xiàn)類:

/**
 * 系統(tǒng)字典服務實現(xiàn)類
 *
 * @author liujunguang1
 * @version V1.0
 * @date 2022/5/20 16:13
 */
@Service
public class SysDictServiceImpl implements SysDictService {
    @Resource
    private SystemContextServiceApi systemContextServiceApi;
    @Resource
    private SysDictCache sysDictCache;
    /**
     * 根據(jù)字典類型編碼獲取字典數(shù)據(jù)
     *
     * @param dictTypeCodes 字典類型編碼值
     * @return List<SysDict>
     */
    @Override
    public List<SysDict> getDictByDictTypeCode(String... dictTypeCodes) {
        List<SysDict> dictTypeCache = sysDictCache.getDictTypeCache(dictTypeCodes);
        if (CollectionUtils.isNotEmpty(dictTypeCache)) {
            return dictTypeCache;
        }
        return systemContextServiceApi.getDictByDictTypeCode(dictTypeCodes).getData();
    }
}

字典緩存服務

可以修改為使用本地緩存方式

/**
 * 字典緩存服務
 *
 * @version V1.0
 * @date 2022/5/19 12:13
 */
@Slf4j
@Service
public class SysDictCache {
    @Resource
    private RedisService redisService;
    /**
     * 獲取字典類型緩存
     *
     * @param dictTypes 字典類型
     * @return 字典列表
     */
    public List<SysDict> getDictTypeCache(String... dictTypes) {
        if (Objects.isNull(redisService)) {
            log.info("redisService 為空,不使用字典緩存");
            return null;
        }
        List<List<SysDict>> dictValues = redisService.getMultiCacheMapValue(CommonConstant.DICT_CACHE_KEY, Arrays.asList(dictTypes));
        if (CollectionUtils.isEmpty(dictValues)) {
            return null;
        }
        List<SysDict> result = new ArrayList<>();
        dictValues.stream().filter(Objects::nonNull).forEach(result::addAll);
        log.debug("查詢字典緩存,dictTypes:{}, 結果:{}", dictTypes, result);
        return result;
    }
    /**
     * 清空字典類型緩存
     *
     * @param dictTypes 字典類型
     */
    public void cleanDictTypeCache(String... dictTypes) {
        if (Objects.isNull(redisService)) {
            return;
        }
        redisService.deleteCacheMapValue(CommonConstant.DICT_CACHE_KEY, dictTypes);
        log.info("清除字典緩存,dictTypes:{}", StringUtils.join(dictTypes));
    }
    /**
     * 添加緩存
     *
     * @param sysDictList 系統(tǒng)字典列表
     */
    public void putDictTypeCache(List<SysDict> sysDictList) {
        if (Objects.isNull(redisService) || CollectionUtils.isEmpty(sysDictList)) {
            return;
        }
        Map<String, List<SysDict>> collect = sysDictList.stream().collect(Collectors.groupingBy(SysDict::getTypeCode));
        for (Map.Entry<String, List<SysDict>> entry : collect.entrySet()) {
            redisService.setCacheMapValue(CommonConstant.DICT_CACHE_KEY, entry.getKey(), entry.getValue());
            log.info("設置字典緩存,dictType:{},結果:{}", entry.getKey(), entry.getValue());
        }
    }
}

到此這篇關于Java分析講解序列化與字典功能的序列化的文章就介紹到這了,更多相關Java序列化內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java實現(xiàn)163郵箱發(fā)送郵件到qq郵箱成功案例

    java實現(xiàn)163郵箱發(fā)送郵件到qq郵箱成功案例

    這篇文章主要為大家分享了java實現(xiàn)163郵箱發(fā)送郵件到qq郵箱成功案例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Java基于Socket實現(xiàn)網(wǎng)絡編程實例詳解

    Java基于Socket實現(xiàn)網(wǎng)絡編程實例詳解

    本文主要給大家介紹的是Java基于Socket實現(xiàn)網(wǎng)絡編程的實例,并給大家介紹了TCP與UDP傳輸協(xié)議,有需要的小伙伴可以來參考下
    2016-07-07
  • Java處理日期時間的方法匯總

    Java處理日期時間的方法匯總

    這篇文章主要給大家介紹了利用Java中的Calendar 類處理日期時間的方法匯總,其中包括取日期的每部分、取當月的第一天或最后一天、求兩個日期之間相隔的天數(shù)以及一年前的日期等等的示例代碼,有需要的朋友們可以直接參考借鑒,下面來一起看看吧。
    2016-12-12
  • spring boot + mybatis實現(xiàn)動態(tài)切換數(shù)據(jù)源實例代碼

    spring boot + mybatis實現(xiàn)動態(tài)切換數(shù)據(jù)源實例代碼

    這篇文章主要給大家介紹了關于spring boot + mybatis實現(xiàn)動態(tài)切換數(shù)據(jù)源的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-10-10
  • SparkSQL使用IDEA快速入門DataFrame與DataSet的完美教程

    SparkSQL使用IDEA快速入門DataFrame與DataSet的完美教程

    本文給大家介紹使用idea開發(fā)Spark SQL 的詳細過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-08-08
  • 如何基于Idea遠程調試tomcat war包及jar包

    如何基于Idea遠程調試tomcat war包及jar包

    這篇文章主要介紹了如何基于Idea遠程調試tomcat war包及jar包,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • 使用JWT作為Spring?Security?OAuth2的token存儲問題

    使用JWT作為Spring?Security?OAuth2的token存儲問題

    這篇文章主要介紹了使用JWT作為Spring?Security?OAuth2的token存儲,大家經常使用的方法有兩種一種是使用JWT作為Token傳遞,一種是使用Redis存儲Token,資源服務器本地訪問Redis校驗Token,需要的朋友可以參考下
    2021-12-12
  • Java定義隊列結構,并實現(xiàn)入隊、出隊操作完整示例

    Java定義隊列結構,并實現(xiàn)入隊、出隊操作完整示例

    這篇文章主要介紹了Java定義隊列結構,并實現(xiàn)入隊、出隊操作,結合完整實例形式分析了java數(shù)據(jù)結構中隊列的定義、入隊、出隊、判斷隊列是否為空、打印隊列元素等相關操作技巧,需要的朋友可以參考下
    2020-02-02
  • IntelliJ IDEA中Scala、sbt、maven配置教程

    IntelliJ IDEA中Scala、sbt、maven配置教程

    這篇文章主要介紹了IntelliJ IDEA中Scala、sbt、maven配置教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java日常練習題,每天進步一點點(44)

    Java日常練習題,每天進步一點點(44)

    下面小編就為大家?guī)硪黄狫ava基礎的幾道練習題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07

最新評論