个人网站建设的方案,做网站付钱方式,wordpress模板缩略图代码,wordpress重装后404介绍本文介绍在项目中时间类型、枚举类型的序列化和反序列化自定义的处理类#xff0c;也可以使用注解。建议枚举都实现一个统一的接口#xff0c;方便处理。我这定义了一个Dict接口。枚举类型注解处理这种方式比较灵活#xff0c;可以让枚举按照自己的方式序列化#xff0…介绍本文介绍在项目中时间类型、枚举类型的序列化和反序列化自定义的处理类也可以使用注解。建议枚举都实现一个统一的接口方便处理。我这定义了一个Dict接口。枚举类型注解处理这种方式比较灵活可以让枚举按照自己的方式序列化可以序列化code值推荐也可以序列化对象。序列化为对象对于前端来说是比较好的前端接收到code值和中文label页面显示label就行了但是对于后端服务之间调用使用feign调用的时候序列化为对象被调用服务的controller层就接收不到这个枚举值了因为接收的是枚举序列化的对象无法反序列化成枚举对象了。除非使用自定义反序列加判断去处理比较麻烦。参考改进枚举工具类定义统一枚举接口package com.common.interfaces;public interface Dict {String name();default Integer getCode() {return null;}default String getLabel() {return null;}
}
序列化code值枚举代码package com.common.enums.app;import com.baomidou.mybatisplus.annotation.EnumValue;
import com.common.interfaces.Dict;
import lombok.AllArgsConstructor;
import lombok.Getter;Getter
AllArgsConstructor
public enum DeliverDateModelEnum implements Dict {SAME(0, 相同时间),DIFFERENT(2, 不同时间),;// mybatis的处理注解 EnumValue// Jackson的序列化处理注解序列化code值JsonValueprivate final Integer code;private final String label;}
package com.common.enums.order;import com.common.exception.E;
import com.common.interfaces.Dict;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AllArgsConstructor;
import lombok.Getter;import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;/*** 订单采购方式枚举*/
Getter
AllArgsConstructor
public enum OrderPurchaseMethodEnum implements Dict {INQUIRY(询价),MALL(商城),;private String label;private static final MapString, OrderPurchaseMethodEnum MAP Arrays.stream(OrderPurchaseMethodEnum.values()).collect(Collectors.toMap(Enum::name, e - e));JsonCreator(mode JsonCreator.Mode.DELEGATING)public static OrderPurchaseMethodEnum resolve(String code) {if (!MAP.containsKey(code)) {throw new Exception(枚举类型错误);}return MAP.get(code);}
}
实体类package com.app.dto;import com.common.enums.apply.DeliverDateModelEnum;
import com.common.enums.order.OrderPurchaseMethodEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;Data
EqualsAndHashCode(callSuper false)
public class ApplyInfoDTO2 implements Serializable {private static final long serialVersionUID 1L;ApiModelProperty(value 主键)private Long id;ApiModelProperty(value 标题, required true)private String title;NotNull(message 时间方式不能为空)private DeliverDateModelEnum deliverDateModel;// 后期会用到private OrderPurchaseMethodEnum purchaseMethod;}
测试代码RestController
Slf4j
RequestMapping(/api/test)
public class TestController2 {PostMapping(value /hh)public ApplyInfoDTO2 test9(RequestBody ApplyInfoDTO2 applyInfoDTO) {System.out.println(hhhhh);applyInfoDTO.setId(55L);System.out.println(---- JacksonUtils.toJson(applyInfoDTO));return applyInfoDTO;}
}请求参数
{id:11,title: dajf,deliverDateModel:2
}响应结果
{id: 55,title: dajf,deliverDateModel: 2,purchaseMethod: null
}序列化对象这里只改枚举就可以了package com.common.enums.app;import com.baomidou.mybatisplus.annotation.EnumValue;
import com.common.interfaces.Dict;
import lombok.AllArgsConstructor;
import lombok.Getter;Getter
AllArgsConstructor
JsonFormat(shape JsonFormat.Shape.OBJECT)
public enum DeliverDateModelEnum implements Dict {SAME(0, 相同时间),DIFFERENT(2, 不同时间),;// mybatis的处理注解EnumValue// 由于上边注解标记序列化为对象了这就不起作用了可以注掉// JsonValueprivate final Integer code;private final String label;}结果请求参数
{id:11,title: dajf,deliverDateModel:0
}响应结果
{id: 55,title: dajf,deliverDateModel: {code: 0,label: 相同时间},purchaseMethod: null
}反序列化处理这就是说前端传code值0后端可以对应到枚举字段上默认的是使用下标ordinal来反序列化的按照0,1,2,3...去对应上如果中跳过了接收值的时候就会报错。比如上边的枚举类DeliverDateModelEnum传0不会报错传2就找不到了错误如下Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.common.enums.apply.DeliverDateModelEnum from number 2: index value outside legal index range [0..1]at [Source: (PushbackInputStream); line: 4, column: 21] (through reference chain: com.cnpc.app.dto.ApplyInfoDTO2[deliverDateModel])解决方案在枚举类加反序列化处理代码JsonCreatorpackage com.common.enums.app;import com.baomidou.mybatisplus.annotation.EnumValue;
import com.common.interfaces.Dict;
import lombok.AllArgsConstructor;
import lombok.Getter;Getter
AllArgsConstructor
JsonFormat(shape JsonFormat.Shape.OBJECT)
public enum DeliverDateModelEnum implements Dict {SAME(0, 相同时间),DIFFERENT(2, 不同时间),;// mybatis的处理注解 EnumValue// 由于上边注解标记序列化为对象了这就不起作用了可以注掉// JsonValueprivate final Integer code;private final String label;private static final MapInteger, DeliverDateModelEnum map Arrays.stream(DeliverDateModelEnum.values()).collect(Collectors.toMap(DeliverDateModelEnum::getCode, e - e));JsonCreator(mode JsonCreator.Mode.DELEGATING)public static DeliverDateModelEnum resolve(Integer code) {if (!map.containsKey(code)) {throw new E(找不到枚举);}return map.get(code);}}以上就是注解的枚举处理方法统一定义接口后为了前端可以通过code值展示枚举中午label所以又写了一个字典解析类将所以实现Dict接口的枚举都拿到然后解析存储再给前端提供一个请求路径。前端存储起来去解析退出的时候可以清除前端缓存。将枚举转字典存储package com.dict.service;import com.common.annotation.DictType;
import com.common.exception.E;
import com.common.interfaces.Dict;
import com.dict.vo.DictItemVO;
import com.dict.vo.DictVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;/*** 系统字典Service*/
Slf4j
Component
public class SystemDictService {/*** 反射要扫描的包路径*/Value(${dict.scanPath:com.company})private String scanPath;/*** 字典集合*/private static SetDictVO DICT_SET new HashSet();/*** 提供给外部获取字典集合的方法** author sun*/public SetDictVO getDictSet() {return DICT_SET;}/*** 启动时扫描*/PostConstructpublic void initDict() {DICT_SET scanDict();}/*** 扫描字典列表*/private SetDictVO scanDict() {// 反射要扫描的包路径Reflections reflections new Reflections(scanPath);// 反射获取所有实现 DictInterface 接口的枚举SetClass? extends Dict monitorClasses reflections.getSubTypesOf(Dict.class);/** 封装字典列表* 过滤掉不是枚举的实现* 反射调用枚举的 values 方法, 获取每个枚举内部的值列表*/return monitorClasses.stream().filter(Class::isEnum).map(sub - {DictVO vo new DictVO();try {/* 这块没有使用到DictType annotation sub.getAnnotation(DictType.class);if (Objects.nonNull(annotation) Strings.isNotBlank(annotation.type())) {// 有DictType注解并且type不是空白时使用注解中的值作为字典的类别vo.setType(annotation.type());} else {// 否则使用类名作为字典的类别vo.setType(sub.getSimpleName());}*/Method valuesMethod sub.getMethod(values);Object valuesObj valuesMethod.invoke(sub);Dict[] values (Dict[]) valuesObj;ListDictItemVO collect Arrays.stream(values).map(item - {// code和label都可以没有全部以name为默认String code item.getCode() ! null ? item.getCode().toString() : item.name();String label item.getLabel() ! null ? item.getLabel() : item.name();return new DictItemVO(code, label);}).collect(Collectors.toList());vo.setItems(collect);} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {log.error({}, e.getMessage(), e);}return vo;})// 这里转map是校验有没有重复的type, 如果存在重复的会报错.collect(Collectors.toMap(item - item, item - item, (a1, a2) - {throw new E(字典类型: a1.getType() , 有重复);})).keySet();}}// controller层提供外部访问
ApiOperation(系统字典列表查询)GetMapping(value /system)public RSetDictVO querySystemDict() {return R.of(systemDictService.getDictSet());}package com.dict.vo;import lombok.Data;import java.util.List;
import java.util.Objects;/*** 字典VO**/
Data
public class DictVO {/*** 字典类别名称*/private String type;/*** 字典项列表*/private ListDictItemVO items;Overridepublic boolean equals(Object o) {if (this o) {return true;}if (o null || getClass() ! o.getClass()) {return false;}DictVO dictVO (DictVO) o;return Objects.equals(type, dictVO.type);}Overridepublic int hashCode() {return Objects.hash(type);}
}
package com.dict.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 字典项*/
Data
NoArgsConstructor
AllArgsConstructor
public class DictItemVO {/*** 编码*/private String code;/*** 标签*/private String label;}
自定义枚举类型处理由于上边规定所有的枚举都需要实现Dict接口下面的反序列化只针对符合条件的处理处理工具类package com.common.config;import com.common.interfaces.Dict;import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;/*** 枚举匹配工具类*/
public class EnumUtil {private static final MapClass? extends Enum?, MapInteger, ? extends Enum? extends Dict CLASS_ENUM_MAP new ConcurrentHashMap(16);SuppressWarnings(unchecked)public static E extends EnumE Dict E match(ClassE enumClass, Integer type) {Map enumMap CLASS_ENUM_MAP.get(enumClass);if (Objects.isNull(enumMap)) {// MapInteger, ? extends Enum? extends Dict unmodifiableMap Arrays.stream(enumClass.getEnumConstants())// 这种表达式写法会报错// .collect(Collectors.toMap(Dict::getCode, v - v));MapInteger, ? extends Enum? extends Dict unmodifiableMap Arrays.stream(enumClass.getEnumConstants()).collect(Collectors.toMap(obj - obj.getCode(), v - v));CLASS_ENUM_MAP.putIfAbsent(enumClass, unmodifiableMap);return (E) unmodifiableMap.get(type);}return (E) enumMap.get(type);}
}
自定义的反序列化类package com.common.config;import com.common.interfaces.Dict;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;import java.io.IOException;/*** 枚举反序列化器*/
public class DictEnumDeserializer extends StdDeserializerDict implements ContextualDeserializer {public DictEnumDeserializer() {super((JavaType) null);}public DictEnumDeserializer(JavaType valueType) {super(valueType);}Overridepublic JsonDeserializer? createContextual(DeserializationContext ctxt, BeanProperty property) {return new DictEnumDeserializer(property.getType());}OverrideSuppressWarnings(all)public Dict deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {return (Dict) EnumUtil.match((Class) _valueClass, p.getIntValue());}
}
注入到spring中注入方式1由于项目中还配置有时间的序列化所以就把它们放一起了。建议使用的把所有的序列化反序列化的都放这。package com.cnpc.common.config;import com.common.interfaces.Dict;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.ClassKey;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;/*** LocalDateTime配置*/
Configuration
// public class LocalDateTimeFormatConfig { 改了一个名字
public class WebCustomerConfig {private static final String DEFAULT_DATE_TIME_PATTERN yyyy-MM-dd HH:mm:ss;private static final String DEFAULT_DATE_PATTERN yyyy-MM-dd;private static final String DEFAULT_TIME_PATTERN HH:mm:ss;// 这里加Primary在项目启动的时候一共会加载12个convert第7个是MappingJackson2HttpMessageConverter
// 处理json映射对象参数的类会采用这个ObjectMapper默认的是 new ObjectMapper();这里自己增加了一些序列化处理的方法BeanPrimarypublic ObjectMapper objectMapper() {ObjectMapper objectMapper new ObjectMapper();// 注册时间的序列化和反序列化处理JavaTimeModule javaTimeModule new JavaTimeModule();javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));objectMapper.registerModule(javaTimeModule);//忽略识别不了的属性objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 注册枚举的处理序列化和反序列的方式SimpleModule sm new SimpleModule();//自定义查找规则sm.setDeserializers(new SimpleDeserializers() {Overridepublic JsonDeserializer? findEnumDeserializer(Class? type, DeserializationConfig config,BeanDescription beanDesc) throws JsonMappingException {JsonDeserializer enumDeserializer super.findEnumDeserializer(type, config, beanDesc);if (enumDeserializer ! null) {return enumDeserializer;}//遍历枚举实现的接口, 查找反序列化器for (Class typeInterface : type.getInterfaces()) {// 如果实现了Dict接口但是没有code值的就返回null如果项目比较规范都有code值或者没有code值的没有实现Dict接口可以去掉下面这个代码if (typeInterface.equals(Dict.class) ){Dict[] enumConstants (Dict[]) type.getEnumConstants();if (Objects.isNull(enumConstants[0].getCode())) {return null;}}enumDeserializer this._classMappings.get(new ClassKey(typeInterface));if (enumDeserializer ! null) {return enumDeserializer;}}return null;}});sm.addDeserializer(Dict.class, new TypeEnumDeserializer());// 增加枚举的序列化方式sm.addSerializer(Dict.class, new JsonSerializerDict() {Overridepublic void serialize(Dict value, JsonGenerator gen, SerializerProvider serializers) throws IOException {// 相当于在枚举类上加 JsonFormat(shape JsonFormat.Shape.OBJECT)返给页面的是一个对象code和label都返回
// gen.writeStartObject();
// gen.writeNumberField(code, value.getCode());
// gen.writeStringField(label, value.getLabel());
// gen.writeEndObject();// 相当于在枚举code字段上加 JsonValue 返回给页面一个code值gen.writeNumber(value.getCode());}Overridepublic void serializeWithType(Dict value, JsonGenerator gen, SerializerProvider serializers,TypeSerializer typeSer) throws IOException {WritableTypeId typeIdDef typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING));serialize(value, gen, serializers);typeSer.writeTypeSuffix(gen, typeIdDef);}});objectMapper.registerModule(sm);return objectMapper;}
}注入方式2下面这种注入会影响项目已经有配置ObjectMapper的地方建议都放一起。如果采用下面这种方式需要自己创建一个MappingJackson2HttpMessageConverter并将converter添加到list的第一个如果添加到最后一个他会先找list中前边的MappingJackson2HttpMessageConverter大约是第7个位置就不会用自己写的。package com.common.config;import com.common.interfaces.Dict;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.ClassKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;/*** 装载枚举序列化器*/
Configuration
Slf4j
public class WebMvcConfig implements WebMvcConfigurer {Overridepublic void configureMessageConverters(ListHttpMessageConverter? converters) {StringHttpMessageConverter stringHttpMessageConverter new StringHttpMessageConverter(StandardCharsets.UTF_8);MappingJackson2HttpMessageConverter converter new MappingJackson2HttpMessageConverter();converter.setObjectMapper(objectMapperForWebConvert());converters.add(0, stringHttpMessageConverter);// 将这个MappingJackson2HttpMessageConverter添加到第一个是为了优先找到否则就有其他MappingJackson2HttpMessageConverter去处理了converters.add(0, converter);}// 这个没有时间的处理配置。public ObjectMapper objectMapperForWebConvert() {ObjectMapper om new ObjectMapper();om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);SimpleModule sm new SimpleModule();//自定义查找规则sm.setDeserializers(new SimpleDeserializers() {Overridepublic JsonDeserializer? findEnumDeserializer(Class? type, DeserializationConfig config,BeanDescription beanDesc) throws JsonMappingException {JsonDeserializer enumDeserializer super.findEnumDeserializer(type, config, beanDesc);if (enumDeserializer ! null) {return enumDeserializer;}//遍历枚举实现的接口, 查找反序列化器for (Class typeInterface : type.getInterfaces()) {// 如果实现了Dict接口但是没有code值的就返回null如果项目比较规范都有code值或者没有code值的没有实现Dict接口可以去掉下面这个代码if (typeInterface.equals(Dict.class)){Dict[] enumConstants (Dict[]) type.getEnumConstants();if (Objects.isNull(enumConstants[0].getCode())) {return null;}}// 这里的classKey不要导错包必须是com.fasterxml.jackson.databind.type.ClassKey否则会找不到导致自定义的反序列化类不起作用enumDeserializer this._classMappings.get(new ClassKey(typeInterface));if (enumDeserializer ! null) {return enumDeserializer;}// 上边的ClassKey导入包错误找不到临时加的
// if (typeInterface.equals(Dict.class)){
// return new DictEnumDeserializer();
// }// return new DictEnumDeserializer();}return null;}});// 添加枚举反序列化处理器sm.addDeserializer(Dict.class, new DictEnumDeserializer());sm.addSerializer(Dict.class, new JsonSerializerDict() {Overridepublic void serialize(Dict value, JsonGenerator gen, SerializerProvider serializers) throws IOException {// 相当于在枚举类上加 JsonFormat(shape JsonFormat.Shape.OBJECT)返给页面的是一个对象code和label都返回
// gen.writeStartObject();
// gen.writeNumberField(code, value.getCode());
// gen.writeStringField(label, value.getLabel());
// gen.writeEndObject();// 相当于在枚举code字段上加 JsonValue 返回给页面一个code值gen.writeNumber(value.getCode());}Overridepublic void serializeWithType(Dict value, JsonGenerator gen, SerializerProvider serializers,TypeSerializer typeSer) throws IOException {WritableTypeId typeIdDef typeSer.writeTypePrefix(gen, typeSer.typeId(value, JsonToken.VALUE_STRING));serialize(value, gen, serializers);typeSer.writeTypeSuffix(gen, typeIdDef);}});om.registerModule(sm);return om;}
}这样就可以测试了。没有实现Dict接口的枚举会采用下一个MappingJackson2HttpMessageConverter的new ObjectMapper去处理按照默认的去处理断点测试第一次赋值加载自定义的ObjectMapper现在converter变成了14个了因为这是注入方式2自己往里面放了2个请求访问时断点org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters(org.springframework.http.HttpInputMessage, org.springframework.core.MethodParameter, java.lang.reflect.Type)注入方式1断点测试启动过程中会放入2个MappingJackson,会看到第7个下移到第8个了注入方式2断点测试第一次启动地址是15536走到自己写的枚举处理改进枚举工具类改进之后即可已返回给前端枚举对象也可以接收对象类型的也可以接收数值也可以接收字符串package com.common.config;import com.common.interfaces.Dict;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;import java.io.IOException;/*** 枚举反序列化器*/
public class DictEnumDeserializer extends StdDeserializerDict implements ContextualDeserializer {public DictEnumDeserializer() {super((JavaType) null);}public DictEnumDeserializer(JavaType valueType) {super(valueType);}Overridepublic JsonDeserializer? createContextual(DeserializationContext ctxt, BeanProperty property) {return new DictEnumDeserializer(property.getType());}// 自定义的反序列化器这个方法需要传JsonParserOverrideSuppressWarnings(all)public Dict deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {return (Dict) EnumUtil.match((Class) _valueClass, p);}
}
package com.common.config;import com.common.interfaces.Dict;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;/*** 枚举匹配工具类
* 改进的枚举工具*/
public class EnumUtil {private static final MapClass? extends Enum?, MapInteger, ? extends Enum? extends Dict CLASS_ENUM_MAP new ConcurrentHashMap(16);SuppressWarnings(unchecked)public static E extends EnumE Dict E match(ClassE enumClass, JsonParser jsonParser) throws IOException {Integer code null;// 接收数值型的if (jsonParser.currentToken() JsonToken.VALUE_NUMBER_INT){code jsonParser.getValueAsInt();// 接收OBJECT类型的参数} else if (jsonParser.currentToken() JsonToken.START_OBJECT){while (jsonParser.nextToken() ! JsonToken.END_OBJECT) {String fieldname jsonParser.getCurrentName();if (code.equals(fieldname)) {jsonParser.nextToken();code jsonParser.getValueAsInt();break;}}// 接收字符串类型的需要判断是纯数字}else if (jsonParser.currentToken() JsonToken.VALUE_STRING){String codestr jsonParser.getValueAsString();if (codestr.matches(^[0-9]*$)) {code Integer.valueOf(codestr);}}if (Objects.isNull(code)){throw new RuntimeException(没有code找不到对应的枚举);}return getDictEnum(enumClass, code);}private static E extends EnumE Dict E getDictEnum(ClassE enumClass, Integer type) {Map enumMap CLASS_ENUM_MAP.get(enumClass);if (Objects.isNull(enumMap)) {MapInteger, ? extends Enum? extends Dict unmodifiableMap Arrays.stream(enumClass.getEnumConstants()).collect(Collectors.toMap(obj - obj.getCode(), v - v));CLASS_ENUM_MAP.putIfAbsent(enumClass, unmodifiableMap);E e (E) unmodifiableMap.get(code);if (Objects.isNull(e)){throw new RuntimeException(指定类型code找不到对应的枚举code code);}return e;}E e (E) enumMap.get(code);if (Objects.isNull(e)){throw new RuntimeException(指定类型code找不到对应的枚举code code);}return e;}// 原来的方法只能接收数值code/*public static E extends EnumE Dict E match(ClassE enumClass, Integer type) {Map enumMap CLASS_ENUM_MAP.get(enumClass);if (Objects.isNull(enumMap)) {MapInteger, ? extends Enum? extends Dict unmodifiableMap Arrays.stream(enumClass.getEnumConstants()).collect(Collectors.toMap(Dict::getCode, v - v));CLASS_ENUM_MAP.putIfAbsent(enumClass, unmodifiableMap);return (E) unmodifiableMap.get(type);}return (E) enumMap.get(type);}*/
}
参考文章https://developer.aliyun.com/article/979501http://events.jianshu.io/p/33e537ea6f10JsonParser的处理https://blog.csdn.net/band_mmbx/article/details/126749515