您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java序列化與字典功能的序列化實(shí)例分析的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Java序列化與字典功能的序列化實(shí)例分析文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。
前端查詢(xún)字典數(shù)據(jù)然后前端轉(zhuǎn)碼
后端查詢(xún)字典值,然后再轉(zhuǎn)碼返回給前段。
本文及時(shí)針對(duì)方案2 進(jìn)行的改進(jìn)
目標(biāo):
在需要返回給前段的字段上添加指定的注解例如:@DictDesc 則根據(jù)該字段定義的值結(jié)合注解配置生成 xxxDesc字段并自動(dòng)賦值為注解屬性值所對(duì)應(yīng)的字典描述;
具體使用的技術(shù)涉及到j(luò)ackson序列化與反序列化,其他JSON工具包也類(lèi)型的效果;
/** * 字典類(lèi)型字段自動(dòng)生成Desc描述字段 */ @Inherited @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @JacksonAnnotationsInside @JsonSerialize(using = DictDescSerializer.class) @JsonDeserialize(using = DictDescDeserializer.class) public @interface DictDesc { /** * 枚舉類(lèi)型的class * 取值:getValue, getCode, getStatus, name * 描述:getDesc * * @return 字典類(lèi)型 */ Class<? extends Enum<? extends DictEnum>>[] enumType() default {}; /** * 字典類(lèi)型分組 * * @return 字典類(lèi)型 */ String[] dictType() default {}; /** * 字典轉(zhuǎn)換失敗時(shí)默認(rèn)值 * * @return String 默認(rèn)值 */ String defaultValue() default ""; /** * 是否拋出異常,默認(rèn)不拋出異常,返回默認(rèn)值 * * @return true 轉(zhuǎn)換失敗則拋出異常,false 異常返回默認(rèn)值 */ boolean throwException() default false; }
該注解中定義了解析該注解需要序列化器與返序列化器:
@JsonSerialize(using = DictDescSerializer.class)
@JsonDeserialize(using = DictDescDeserializer.class)
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; /** * 字典類(lèi)型返序列化器 * * @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ù)類(lèi)型 */ private Class<?> rawClass; /** * 默認(rèn)轉(zhuǎn)換器 */ private ConversionService converter; /** * 設(shè)置方法 */ 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("類(lèi):{},字典屬性:{},沒(méi)有寫(xiě)入方法:{},不設(shè)置值!", 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ù)類(lèi)型轉(zhuǎn)換為目標(biāo)類(lèi)型 * * @param value 字符串值 * @return 目標(biāo)類(lèi)型值 * @throws IOException */ public Object getValue(String value) throws IOException { return converter.convert(value, this.rawClass); } /** * 設(shè)置字典會(huì)限制 * * @param result 字典value * @param currentName 當(dāng)前屬性名稱(chēng) * @param currentValue 當(dāng)前對(duì)象 */ 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("類(lèi):{},字典屬性:{},回顯異常:{}", 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; /** * 構(gòu)造方法 * * @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(); // 添加轉(zhuǎn)換之后的字段: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; /** * 字典轉(zhuǎn)換工具類(lèi) * * @author liujunguang1 * @version V1.0 * @date 2022/5/20 23:19 */ @Slf4j public class DictDescSerializerUtils { /** * 獲取字典信息 * * @param dict 字典對(duì)象 * @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("字典轉(zhuǎn)換異常, 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(); } } /** * 獲取枚舉類(lèi)型的描述信息 * * @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 字典名稱(chēng) */ 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())); } }
/** * 字典服務(wù)類(lèi) * * @author liujunguang1 * @version V1.0 * @date 2022/5/20 16:03 */ public interface SysDictService { /** * 根據(jù)字典類(lèi)型code獲取字典列表 * * @param dictTypeCodes 字典類(lèi)型code * @return List<SysDict> */ public List<SysDict> getDictByDictTypeCode(String... dictTypeCodes); }
服務(wù)實(shí)現(xiàn)類(lèi):
/** * 系統(tǒng)字典服務(wù)實(shí)現(xiàn)類(lèi) * * @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ù)字典類(lèi)型編碼獲取字典數(shù)據(jù) * * @param dictTypeCodes 字典類(lèi)型編碼值 * @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(); } }
可以修改為使用本地緩存方式
/** * 字典緩存服務(wù) * * @version V1.0 * @date 2022/5/19 12:13 */ @Slf4j @Service public class SysDictCache { @Resource private RedisService redisService; /** * 獲取字典類(lèi)型緩存 * * @param dictTypes 字典類(lèi)型 * @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("查詢(xún)字典緩存,dictTypes:{}, 結(jié)果:{}", dictTypes, result); return result; } /** * 清空字典類(lèi)型緩存 * * @param dictTypes 字典類(lèi)型 */ 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("設(shè)置字典緩存,dictType:{},結(jié)果:{}", entry.getKey(), entry.getValue()); } } }
關(guān)于“Java序列化與字典功能的序列化實(shí)例分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Java序列化與字典功能的序列化實(shí)例分析”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。