java语言支持类的序列化,java序列化概念
目录
两种解决方案字典注解定义字典序列化与返序列化器的实现字典序列化与反序列工具类字典转换服务类字典缓存服务
两种解决方案
前端查询字典数据然后前端转码后端查询字典值,然后再转码返回给前段。本文及时针对方案注射毒品进行的改进
目标:
在需要返回给前段的字段上添加指定的注解例如:@DictDesc则根据该字段定义的值结合注解配置生成xxxDesc字段并自动赋值为注解属性值所对应的字典描述;
具体使用的技术涉及到杰克逊序列化与反序列化,其他数据工具包也类型的效果;
字典注解定义
/** * 字典类型字段自动生成表名描述字段*/@ Inherited @ Target(元素类型.字段)@保留(保留策略.运行时)@ documentated @ jacksonotinside @ JSON serialize(使用=dictdescserializer。class)@ JSON des serialize(using=dictdescdescriselier。class)public @ interface dict desc {/* * *枚举类型的类别*取值:获取值,获取代码,获取状态,名称*描述:getDesc * * @return字典类型*/类?扩展枚举?扩展字典[]枚举类型()默认值{ };/** * 字典类型分组* * @返回字典类型*/String[] dictType()默认值{ };/** * 字典转换失败时默认值* * @返回字符串默认值*/String默认值()默认值"";/** * 是否抛出异常,默认不抛出异常,返回默认值* * @返回真实的转换失败则抛出异常,假的异常返回默认值*/布尔throwException()默认值为false}该注解中定义了解析该注解需要序列化器与返序列化器:
@JsonSerialize(使用=DictDescSerializer.class)
@JsonDeserialize(使用=DictDescDeserializer.class)
字典序列化与返序列化器的实现
导入com。更快的XML。杰克逊。核心。jacksonexception导入com。更快的XML。杰克逊。核心。JSON解析器;导入com。更快的XML。杰克逊。数据绑定。豆属性;导入com。更快的XML。杰克逊。数据绑定。沙漠化语境;导入com。更快的XML。杰克逊。数据绑定。JSON反序列化器;导入com。更快的XML。杰克逊。数据绑定。jsonmappingexception导入com。更快的XML。杰克逊。数据绑定。活该。外部izer导入com。林艾米。常见。迪克特。注释。迪克特desc;导入com。林艾米。常见。迪克特。服务。impl。dictdescserializerutils进口龙目岛100 . NoArgsConstructor导入龙目岛。外部人员。SLF 4j。SLF 4j;导入org。spring框架。豆子。bean utils导入org。spring框架。核心。转换。转换服务;导入org。spring框架。核心。转换。支持。defaultconversionservice导入Java。豆子。属性描述符;导入Java。io。io异常;导入Java。郎。反思。方法;导入Java。util。对象;/** * 字典
类型返序列化器 * * @author liujunguang1 * @version V1.0 * @date 2022/5/20 21:08 */@Slf4j@NoArgsConstructorpublic class DictDescDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer { /** * 生成序列化字段后缀 */ private static final String LABEL_SUFFIX = "Desc"; /** * 参数类型 */ 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; } /** * 将数据类型转换为目标类型 * * @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@NoArgsConstructorpublic 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 */@Slf4jpublic 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 { /** * 根据字典类型code获取字典列表 * * @param dictTypeCodes 字典类型code * @return List<SysDict> */ public List<SysDict> getDictByDictTypeCode(String... dictTypeCodes);}
服务实现类:
/** * 系统字典服务实现类 * * @author liujunguang1 * @version V1.0 * @date 2022/5/20 16:13 */@Servicepublic class SysDictServiceImpl implements SysDictService { @Resource private SystemContextServiceApi systemContextServiceApi; @Resource private SysDictCache sysDictCache; /** * 根据字典类型编码获取字典数据 * * @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@Servicepublic 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 系统字典列表 */ 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序列化内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。