两种解决方案
- 前端查询字典数据然后前端转码
- 后端查询字典值,然后再转码返回给前段。
本文及时针对方案2 进行的改进
目标:
在需要返回给前段的字段上添加指定的注解例如:@DictDesc 则根据该字段定义的值结合注解配置生成 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)
字典序列化与返序列化器的实现
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
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
字典序列化与反序列工具类
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); } ListsysDictList = 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*/ public List getDictByDictTypeCode(String... dictTypeCodes); }
服务实现类:
/** * 系统字典服务实现类 * * @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; /** * 根据字典类型编码获取字典数据 * * @param dictTypeCodes 字典类型编码值 * @return List*/ @Override public List getDictByDictTypeCode(String... dictTypeCodes) { List 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 ListgetDictTypeCache(String... dictTypes) { if (Objects.isNull(redisService)) { log.info("redisService 为空,不使用字典缓存"); return null; } List > dictValues = redisService.getMultiCacheMapValue(CommonConstant.DICT_CACHE_KEY, Arrays.asList(dictTypes)); if (CollectionUtils.isEmpty(dictValues)) { return null; } List
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 sysDictList) { if (Objects.isNull(redisService) || CollectionUtils.isEmpty(sysDictList)) { return; } Map > collect = sysDictList.stream().collect(Collectors.groupingBy(SysDict::getTypeCode)); for (Map.Entry > entry : collect.entrySet()) { redisService.setCacheMapValue(CommonConstant.DICT_CACHE_KEY, entry.getKey(), entry.getValue()); log.info("设置字典缓存,dictType:{},结果:{}", entry.getKey(), entry.getValue()); } } }
到此这篇关于Java分析讲解序列化与字典功能的序列化的文章就介绍到这了,更多相关Java序列化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!