域名备案需要网站吗,海外推广营销,北京做电商网站设计,软件工程很难学吗目录 1.枚举简介 
1.1.规范 
1.2.枚举类真实的样子 
1.3.枚举类的特点 
1.4.枚举可以使用的方法 
1.4.1.toString()方法 
1.4.2.valueOf方法 
1.4.3.values方法 
1.4.4.ordinal方法 
1.5.枚举的用法 
1.5.1.常量 
1.5.2.switch 
1.5.3.枚举中增加方法 
1.5.4.覆盖枚举方法 
1.5…目录 1.枚举简介 
1.1.规范 
1.2.枚举类真实的样子 
1.3.枚举类的特点 
1.4.枚举可以使用的方法 
1.4.1.toString()方法 
1.4.2.valueOf方法 
1.4.3.values方法 
1.4.4.ordinal方法 
1.5.枚举的用法 
1.5.1.常量 
1.5.2.switch 
1.5.3.枚举中增加方法 
1.5.4.覆盖枚举方法 
1.5.5.实现接口 
1.5.5.1.情况 1在 enum 类中实现接口 
1.5.5.2.情况 2让枚举类中的对象分别实现接口中的方法 
1.5.6.在接口中使用枚举类 
1.5.7.使用枚举集合 
1.5.7.1.EnumSet 
1.5.7.2.EnumMap 
2.序列化和反序列化 
2.1.什么是序列化和反序列化 
2.2.什么是serialVersionUID序列化ID 
2.3.什么类型的数据不能被序列化 
3.jackson 
3.1.jackson序列化writeValueAsString 
3.2.jackson反序列化readValue 
3.3.集合转换 
3.4.JsonProperty 
3.5.ObjectMapper的一些配置 
3.6.JsonParser 
3.6.1.创建 
3.6.2.解析 
4.枚举的序列化 
4.1.ordinal索引 
4.2.时序图 
4.3.json枚举序列化/反序列化处理 
4.3.1.方法一使用JsonCreator和JsonValue 
4.3.2.方法二自定义序列化/反序列化方法 
4.4.mybatis枚举序列化/反序列化处理 
4.4.1.TypeHandler 
4.4.2.配置步骤 
5.IDEA2019取消枚举提示 
6.查看枚举调用的地方 1.枚举简介 
枚举类型enum type是指由一组固定的常量组成合法的类型。 枚举类格式 
public enum SexEnum {MAN, WOMAN
} 
1.1.规范 1.2.枚举类真实的样子 
1、使用javac 命令编译得到.class文件 
2、使用命令 javap 对class文件进行反编译 
javac Sex.java 
javap Sex.class 
得到如下结果 
Compiled from Sex.java 
public final class Sex extends java.lang.EnumSex {public static final Sex MAN;public static final Sex WOMAN;public static Sex[] values();public static Sex valueOf(java.lang.String);static {};
} 
3、这里其实是创建了2个对象 
public final class Sex extends java.lang.EnumSex {public static final Sex MAN  new Sex();public static final Sex WOMAN  new Sex();public static Sex[] values();public static Sex valueOf(java.lang.String);static {};
} 
1.3.枚举类的特点 
1、枚举类是通过final修饰不能被继承 2、枚举类默认继承了枚举类型 java.lang.Enum 3、枚举类的第一行罗列的是枚举类对象并且是常量存储所以枚举类的第一行写的是常量名称默认存储了枚举对象。 4、枚举类的构造器是私有的。 5、枚举类相当于多例设计模式 1.4.枚举可以使用的方法 
把上面的枚举类加上code和name 
public enum SexEnum {MAN(1, 男),WOMAN(2, 女);private Integer code;private String name;SexEnum(Integer code, String name) {this.code  code;this.name  name;}public Integer getCode() {return code;}public String getName() {return name;}
} 
1.4.1.toString()方法 
这个方法会返回枚举常量名 
// MAN
System.out.println(SexEnum.MAN.toString());
// WOMAN
System.out.println(SexEnum.WOMAN.toString()); 
1.4.2.valueOf方法 
这个方法用于构建枚举类传入枚举类常量名即可。 
SexEnum sexEnum  SexEnum.valueOf(MAN);
// 男
System.out.println(sexEnum.getName());
try {// 报错: java.lang.IllegalArgumentException: No enum constant com.leelen.scd.api.amc.enums.SexEnum.UNKNOWNSystem.out.println(SexEnum.valueOf(UNKNOWN).getName());
} catch (IllegalArgumentException e) {e.printStackTrace();
} 
如果不存在传入的枚举常量那么会报错 java.lang.IllegalArgumentException:  No enum constant com.leelen.scd.api.amc.enums.SexEnum.UNKNOWN     at java.lang.Enum.valueOf(Enum.java:238)     at com.leelen.scd.api.amc.enums.SexEnum.valueOf(SexEnum.java:3)     at com.leelen.scd.api.amc.enums.UseSex.main(UseSex.java:28) 1.4.3.values方法 
使用枚举类名进行调用会返回所有枚举常量的数组 1.4.4.ordinal方法 
这个方法会返回枚举常量在enum中声明的位置从0开始 
SexEnum[] sexEnum  SexEnum.values();
for (SexEnum s : sexEnum) {System.out.println(s.getCode()  ,  s.getName()  ,  s.ordinal());
} 
打印结果 1,男,0 2,女,1 1.5.枚举的用法 
1.5.1.常量 
public enum ColorEnum {RED, GREEN, BLANK, YELLOW
} 
1.5.2.switch 
public static void getSexName(SexEnum sexEnum) {switch (sexEnum) {case MAN:System.out.println(男);break;case WOMAN:System.out.println(女);break;default:break;}
} 
这里不要使用 SexEnum.MAN, 不然会提示An enum switch case label must be the unqualified name of an enumeration constant 1.5.3.枚举中增加方法 
public class EnumTest {public static void main(String[] args) {ErrorCodeEnum errorCode  ErrorCodeEnum.SUCCESS;System.out.println(状态码  errorCode.code()  状态信息  errorCode.msg());}
}enum ErrorCodeEnum {SUCCESS(1000, success),PARAM_ERROR(1001, parameter error),SYS_ERROR(1003, system error),NAMESPACE_NOT_FOUND(2001, namespace not found),NODE_NOT_EXIST(3002, node not exist),NODE_ALREADY_EXIST(3003, node already exist),UNKNOWN_ERROR(9999, unknown error);private int code;private String msg;ErrorCodeEnum(int code, String msg) {this.code  code;this.msg  msg;}public int code() {return code;}public String msg() {return msg;}public static ErrorCodeEnum getErrorCode(int code) {for (ErrorCodeEnum it : ErrorCodeEnum.values()) {if (it.code()  code) {return it;}}return UNKNOWN_ERROR;}
} 
1.5.4.覆盖枚举方法 
我们可以覆盖一些枚举中的方法用于实现自己的业务比如我们可以覆盖 toString() 方法实现代码如下 
public class EnumTest {public static void main(String[] args) {ColorEnum colorEnum  ColorEnum.RED;System.out.println(colorEnum.toString());}
}enum ColorEnum {RED(红色, 1), GREEN(绿色, 2), BLANK(白色, 3), YELLOW(黄色, 4);//  成员变量private String name;private int index;//  构造方法private ColorEnum(String name, int index) {this.name  name;this.index  index;}//覆盖方法Overridepublic String toString() {return this.index    this.name;}
} 1.5.5.实现接口 
枚举类可以用来实现接口但不能用于继承类因为枚举默认继承了 java.lang.Enum 类在 Java 语言中允许实现多接口但不能继承多个父类实现代码如下 1.5.5.1.情况 1在 enum 类中实现接口 
public class EnumTest {public static void main(String[] args) {ColorEnum colorEnum  ColorEnum.RED;colorEnum.print();System.out.println(颜色  colorEnum.getInfo());}
}interface Behaviour {void print();String getInfo();
}enum ColorEnum implements Behaviour {RED(红色, 1), GREEN(绿色, 2), BLANK(白色, 3), YELLOW(黄色, 4);private String name;private int index;private ColorEnum(String name, int index) {this.name  name;this.index  index;}Overridepublic void print() {System.out.println(this.index    this.name);}Overridepublic String getInfo() {return this.name;}
} 
1.5.5.2.情况 2让枚举类中的对象分别实现接口中的方法 
public enum ColorEnum implements Behaviour{RED(红色, 1) {Overridepublic void print() {}Overridepublic String getInfo() {return null;}}, GREEN(绿色, 2) {Overridepublic void print() {}Overridepublic String getInfo() {return null;}}, BLANK(白色, 3) {Overridepublic void print() {}Overridepublic String getInfo() {return null;}}, YELLOW(黄色, 4) {Overridepublic void print() {}Overridepublic String getInfo() {return null;}};private String name;private int index;private ColorEnum(String name, int index) {this.name  name;this.index  index;}
} 1.5.6.在接口中使用枚举类 
我们可以在一个接口中创建多个枚举类用它可以很好的实现“多态”也就是说我们可以将拥有相同特性但又有细微实现差别的枚举类聚集在一个接口中实现代码如下 
public class EnumTest {public static void main(String[] args) {// 赋值第一个枚举类ColorInterface colorEnum  ColorInterface.ColorEnum.RED;System.out.println(colorEnum);// 赋值第二个枚举类colorEnum  ColorInterface.NewColorEnum.NEW_RED;System.out.println(colorEnum);}
}interface ColorInterface {enum ColorEnum implements ColorInterface {GREEN, YELLOW, RED}enum NewColorEnum implements ColorInterface {NEW_GREEN, NEW_YELLOW, NEW_RED}
} 
1.5.7.使用枚举集合 
在 Java 语言中和枚举类相关的还有两个枚举集合类 java.util.EnumSet 和 java.util.EnumMap使用它们可以实现更多的功能。 
1.5.7.1.EnumSet 
使用 EnumSet 可以保证元素不重复并且能获取指定范围内的元素示例代码如下 
public class EnumTest {public static void main(String[] args) {ListColorEnum list  new ArrayList();list.add(ColorEnum.RED);list.add(ColorEnum.RED);  // 重复元素list.add(ColorEnum.YELLOW);list.add(ColorEnum.GREEN);// 去掉重复数据EnumSetColorEnum enumSet  EnumSet.copyOf(list);System.out.println(去重  enumSet);// 获取指定范围的枚举获取所有的失败状态EnumSetErrorCodeEnum errorCodeEnums  EnumSet.range(ErrorCodeEnum.ERROR, ErrorCodeEnum.UNKNOWN_ERROR);System.out.println(所有失败状态  errorCodeEnums);}
}enum ColorEnum {RED(红色, 1), GREEN(绿色, 2), BLANK(白色, 3), YELLOW(黄色, 4);private String name;private int index;private ColorEnum(String name, int index) {this.name  name;this.index  index;}
}enum ErrorCodeEnum {SUCCESS(1000, success),ERROR(2001, parameter error),SYS_ERROR(2002, system error),NAMESPACE_NOT_FOUND(2003, namespace not found),NODE_NOT_EXIST(3002, node not exist),NODE_ALREADY_EXIST(3003, node already exist),UNKNOWN_ERROR(9999, unknown error);private int code;private String msg;ErrorCodeEnum(int code, String msg) {this.code  code;this.msg  msg;}public int code() {return code;}public String msg() {return msg;}
} 
1.5.7.2.EnumMap 
public class EnumTest {public static void main(String[] args) {EnumMapColorEnum, String enumMap  new EnumMap(ColorEnum.class);enumMap.put(ColorEnum.RED, 红色);enumMap.put(ColorEnum.GREEN, 绿色);enumMap.put(ColorEnum.BLANK, 白色);enumMap.put(ColorEnum.YELLOW, 黄色);System.out.println(ColorEnum.RED  :  enumMap.get(ColorEnum.RED));}
}enum ColorEnum {RED, GREEN, BLANK, YELLOW;
} 2.序列化和反序列化 
2.1.什么是序列化和反序列化 
序列化过程是指把一个 Java 对象变成二进制内容实质上就是一个 byte[]。因为序列化后可以把 byte[] 保存到文件中或者把 byte[] 通过网络传输到远程(IO)如此就相当于把 Java 对象存储到文件或者通过网络传输出去了。 一个 Java 对象要能序列化必须实现一个特殊的java.io.Serializable接口它的定义如下 
package java.io;
public interface Serializable {
} 
Serializable 没有定义任何方法它是一个空接口。这样的空接口称为“标记接口”(Marker Interface)实现了标记接口的类仅仅是给自身贴了个“标记”并没有增加任何方法。 反序列化过程把一个二进制内容(也就是 byte[])变回 Java 对象。有了反序列化保存到文件中的 byte[] 又可以“变回” Java 对象或者从网络上读取 byte[] 并把它“变回” Java 对象。 为什么需要序列化与反序列化 
当两个进程进行远程通信时可以相互发送各种类型的数据包括文本、图片、音频、视频等 而这些数据都会以二进制序列的形式在网络上传送。 
当两个 Java 进程进行通信时需要 Java 序列化与反序列化实现进程间的对象传送。换句话说一方面发送方需要把这个 Java 对象转换为字节序列然后在网络上传送另一方面接收方需要从字节序列中恢复出 Java 对象。 代码 
import lombok.Data;
import java.io.Serializable;
Data
public class Student implements Serializable {private String name;private Integer age;private Integer score;
} 
import java.io.*;
public class TypeDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {serialize();deserialize();}/*** 序列化*/public static void serialize() throws IOException {Student student  new Student();student.setName(new);student.setAge(18);student.setScore(100);ObjectOutputStream objectOutputStream new ObjectOutputStream(new FileOutputStream(new File(student.txt)));objectOutputStream.writeObject(student);objectOutputStream.close();System.out.println(序列化成功已经生成student.txt文件);System.out.println();}/*** 反序列化*/public static void deserialize() throws IOException, ClassNotFoundException {ObjectInputStream objectInputStream new ObjectInputStream(new FileInputStream(new File(student.txt)));Student student  (Student) objectInputStream.readObject();objectInputStream.close();System.out.println(反序列化结果为  student);}
} 
结果 
序列化成功已经生成student.txt文件 反序列化结果为Student(namenew, age18, score100) 2.2.什么是serialVersionUID序列化ID 
private static final long serialVersionUID  -4392658638228508589L; 
serialVersionUID 是一个常数用于唯一标识可序列化类的版本。 
从输入流构造对象时JVM 在反序列化过程中检查此常数。如果正在读取的对象的 serialVersionUID 与类中指定的序列号不同则 JVM 抛出InvalidClassException。这是为了确保正在构造的对象与具有相同 serialVersionUID 的类兼容。 我们先调用serialize()方法把上面的Student对象序列化进student.txt文件中。然后修改Student类的内容去掉其中一个字段 
Data
public class Student implements Serializable {private String name;private Integer age;
} 
再调用反序列化方法deserialize()结果报错 
Exception in thread main java.io.InvalidClassException: com.codejam.enums.demo.type.Student; local class incompatible: stream classdesc serialVersionUID  -6951954515964250676, local class serialVersionUID  7327139321132172307 这是因为serialVersionUID 是可选的。如果不显式声明Java 编译器将自动生成一个。 2.3.什么类型的数据不能被序列化 
声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态transient代表对象的临时数据。 3.jackson 
由于Spring自带的序列化和反序列化使用的是jackson所以项目不使用fastjson。 3.1.jackson序列化writeValueAsString 
先创建对象 
Data
public class Student {private String name;private Integer age;
} 
创建保护集合的对象 
Data
public class Room {ListStudent studentList;
} 
1、使用writeValueAsString将一个对象序列化为字符串 
public static void main(String[] args) throws JsonProcessingException {ObjectMapper objectMappernew ObjectMapper();Student studentnew Student();student.setName(abc);student.setAge(18);String s  objectMapper.writeValueAsString(student);System.out.println(s);
} 
打印 
{name:abc,age:18}、 
2、使用writeValueAsString 将一个包含集合的对象序列化为字符串 
public static void main(String[] args) throws JsonProcessingException {ListStudent list  new ArrayList();for (int i  0; i  3; i) {Student student  new Student();student.setName(name  i);student.setAge(i);list.add(student);}Room classRoom  new Room();classRoom.setStudentList(list);ObjectMapper objectMapper  new ObjectMapper();String s  objectMapper.writeValueAsString(classRoom);System.out.println(s);
} 
打印 
{studentList:[{name:name0,age:0},{name:name1,age:1},{name:name2,age:2}]} 3.2.jackson反序列化readValue 
使用readValue将字符串转换为student对象 
public static void main(String[] args) throws JsonProcessingException {ObjectMapper objectMappernew ObjectMapper();String s  {\name\:\abc\,\age\:18};Student student  objectMapper.readValue(s, Student.class);System.out.println(student);
} 
使用readValue将字符串转为对象包含集合 
public static void main(String[] args) throws JsonProcessingException {String s  {\studentList\:[{\name\:\name0\,\age\:0},{\name\:\name1\,\age\:1},{\name\:\name2\,\age\:2}]};ObjectMapper objectMapper  new ObjectMapper();Room room  objectMapper.readValue(s, Room.class);System.out.println(room);
} 3.3.集合转换 
public static void main(String[] args) throws JsonProcessingException {String listStr  [{\name\:\李四\,\age\:1},{\name\:\张三\,\age\:2}];ObjectMapper objectMapper  new ObjectMapper();ListStudent students  objectMapper.readValue(listStr, new TypeReferenceListStudent() {});System.out.println(students);
} 
3.4.JsonProperty 
如果序列化的时候名称要更改的话则可以使用JsonProperty 3.5.ObjectMapper的一些配置 
通过以下设置会在序列化和反序列化时忽略无法解析和为空的字段 
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;ObjectMapper objectMapper  new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
3.6.JsonParser 
JsonParser 类是底层 Json解析器。 JsonParser实现相较于 ObjectMapper 更底层因此解析速度更快但相对复杂。 
3.6.1.创建 
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;public static void main(String[] args) throws IOException {String carJson  { \brand\ : \Mercedes\, \doors\ : 5 };JsonFactory factory  new JsonFactory();JsonParser parser  factory.createParser(carJson);
} 
createParser()方法传入 Reader, InputStream, URL, byte[] 或 char[] 参数可以实现解析不同来源 json 数据。 
3.6.2.解析 
JsonParser 工作方式是将 json 分解成一系列标记 (token) 逐个迭代这些标记进行解析 
public static void main(String[] args) throws IOException {String carJson  { \brand\ : \Mercedes\, \doors\ : 5 };JsonFactory factory  new JsonFactory();JsonParser parser   factory.createParser(carJson);while(!parser.isClosed()){JsonToken jsonToken  parser.nextToken();System.out.println(jsonToken    jsonToken);}
} 
输出结果 
jsonToken  START_OBJECT 
jsonToken  FIELD_NAME 
jsonToken  VALUE_STRING 
jsonToken  FIELD_NAME 
jsonToken  VALUE_NUMBER_INT 
jsonToken  END_OBJECT 
jsonToken  null 通过 JsonParser 的 nextToken() 方法获得 JsonToken我们可以检查 JsonToken 实例的类型JsonToken 类提供了一组常量表示标记类型 
package com.fasterxml.jackson.core;
public enum JsonToken
{NOT_AVAILABLE(null, JsonTokenId.ID_NOT_AVAILABLE),START_OBJECT({, JsonTokenId.ID_START_OBJECT),END_OBJECT(}, JsonTokenId.ID_END_OBJECT),START_ARRAY([, JsonTokenId.ID_START_ARRAY),END_ARRAY(], JsonTokenId.ID_END_ARRAY),FIELD_NAME(null, JsonTokenId.ID_FIELD_NAME),VALUE_EMBEDDED_OBJECT(null, JsonTokenId.ID_EMBEDDED_OBJECT),VALUE_STRING(null, JsonTokenId.ID_STRING),VALUE_NUMBER_INT(null, JsonTokenId.ID_NUMBER_INT),VALUE_NUMBER_FLOAT(null, JsonTokenId.ID_NUMBER_FLOAT),VALUE_TRUE(true, JsonTokenId.ID_TRUE),VALUE_FALSE(false, JsonTokenId.ID_FALSE),VALUE_NULL(null, JsonTokenId.ID_NULL),;
} 
如果标记指针指向的是字段JsonParser 的 getCurrentName() 方法返回当前字段名称。 
getValueAsString() 返回当前标记值的字符串类型同理 getValueAsInt() 返回整型值其他方法 public static void main(String[] args) throws IOException {String json  { \name\ : \tom\, \age\ : 28, \height\: 1.75, \ok\: true};JsonFactory factory  new JsonFactory();JsonParser parser  factory.createParser(json);while (!parser.isClosed()) {JsonToken token  parser.nextToken();if (JsonToken.FIELD_NAME  token) {String fieldName  parser.getCurrentName();System.out.print(fieldName  : );parser.nextToken();switch (fieldName) {case name:System.out.println(parser.getValueAsString());break;case age:System.out.println(parser.getValueAsInt());break;case height:System.out.println(parser.getValueAsDouble());break;case ok:System.out.println(parser.getValueAsBoolean());break;}}}
} 4.枚举的序列化 
4.1.ordinal索引 
枚举默认是使用索引ordinal 来进行序列化反序列化操作的 例如我这边定义了枚举1, 3  它对应的索引是0,1 
Getter
Accessors(fluent  true)
AllArgsConstructor
public enum AmcManagementModeEnum implements IDictionaryEnum {UNIFIED_AUTHORIZATION_MANAGEMENT(1, 统一授权管理),//SEMI_AUTHORIZED_MANAGEMENT(2, 半授权管理),INDEPENDENT_MANAGEMENT(3, 独立管理),;/*** 字典码值*/private Integer code;/*** 字典描述*/private String desc;
} 
前端请求0的时候对应的是第一个 1, 统一授权管理。 请求1的时候对应的是第二个 3, 独立管理。 但如果我请求2的话则会报错越界了。 
Invalid JSON input: Cannot deserialize value of type com.leelen.scd.module.amc.enums.AmcManagementModeEnum from number 2: index value outside legal index range [0..1]; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.leelen.scd.module.amc.enums.AmcManagementModeEnum from number 2: index value outside legal index range [0..1]\n at [Source: (PushbackInputStream); line: 17, column: 31] (through reference chain: com.leelen.scd.base.common.entity.RequestDTO[\body\]-com.leelen.scd.base.common.entity.PagerReqDTO[\params\]-com.leelen.scd.module.amc.vo.AmcNeighInfoPageReq[\managementMode\]) 4.2.时序图 4.3.json枚举序列化/反序列化处理 
4.3.1.方法一使用JsonCreator和JsonValue 
JsonCreator 标记在反序列化时的初始化函数入参为对应该枚举类型的值。 
JsonVale标记在序列化时枚举对应生成的值。 
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.leelen.scd.base.common.enums.IDictEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.experimental.Accessors;import java.util.Objects;Getter
Accessors(fluent  true)
AllArgsConstructor
public enum AmcManagementModeEnum implements IDictEnum{UNIFIED_AUTHORIZATION_MANAGEMENT( 1, 统一授权管理),//SEMI_AUTHORIZED_MANAGEMENT(2, 半授权管理),INDEPENDENT_MANAGEMENT(3, 独立管理),;/*** 字典码值*/private Integer code;/*** 字典描述*/private String desc;/*** 处理入参定义转换函数parse将code值入参转成对应的枚举类型* 在反序列化的时候Jackson会自动调用这个方法去自动帮我们转换*/JsonCreatorpublic static AmcManagementModeEnum parse(Integer code) {if (Objects.isNull(code)) {return null;}for (AmcManagementModeEnum item : AmcManagementModeEnum.values()) {if (item.code.equals(code)) {return item;}}return null;}/*** 处理出参在getter方法标记序列化后的值*/JsonValuepublic Integer code() {return code;}} 
使用枚举 请求参数 
import com.leelen.scd.module.amc.enums.AmcManagementModeEnum;
import lombok.Data;
Data
public class AmcNeighInfoPageReq {/*** 小区管理模式*/private AmcManagementModeEnum managementMode;
} 
响应参数 
Data
public class AmcNeighInfoPageRes {/*** 小区管理模式*/private AmcManagementModeEnum managementMode;
} 
验证 
RestController
RequestMapping(/web/system/community/amc)
public class AmcNeighInfoController {/*** 分页*/RequestMapping(/page)public ResponseDTOAmcNeighInfoPageRes page(RequestBody final RequestDTOPagerReqDTOAmcNeighInfoPageReq request) {AmcNeighInfoPageRes res  new AmcNeighInfoPageRes();res.setManagementMode(request.getBody().getParams().getManagementMode());return ResponseHelper.successResponse(request.getHeader(), res);}
} 4.3.2.方法二自定义序列化/反序列化方法 
1、首先定义接口IDictEnum。  这里指定反序列化的方法EnumJsonDeserializer 这里指定序列化的方法EnumJsonSerializer 
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;JsonDeserialize(using  EnumJsonDeSerializer.class)
JsonSerialize(using  EnumJsonSerializer.class)
public interface IDictEnum {/*** 获得字典码值*/Integer code();/*** 获得字典描述, 这里不能用name, 因为java.lang.Enum已经定义了name*/String desc();} 
2、反序列化方法EnumJsonDeserializer 
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;import java.io.IOException;
import java.util.Arrays;public class EnumJsonDeSerializer extends JsonDeserializerIDictEnum implements ContextualDeserializer {private Class? extends IDictEnum clazz;public EnumJsonDeSerializer() {}public EnumJsonDeSerializer(Class? extends IDictEnum clazz) {this.clazz  clazz;}Overridepublic IDictEnum deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {String param  jsonParser.getText();IDictEnum[] enumConstants  clazz.getEnumConstants();JsonStreamContext parsingContext  jsonParser.getParsingContext();IDictEnum iDictEnum  Arrays.stream(enumConstants).filter(x - {//x.toString(),取枚举的具体值如xxx.enums.share.DelFlagEnum 枚举里的“NOT_DELETE”//从而使得两种形式都能识别String enumCodeStr  x.toString();return enumCodeStr.equals(param) || param.equals(x.code()  );}).findFirst().orElse(null);/*if (null  iEnum) {String msg  String.format(枚举类型%s从%s未能转换成功, clazz.toString(), param);throw new Exception(msg);}*/return iDictEnum;}Overridepublic Class? handledType() {return IDictEnum.class;}SuppressWarnings({unchecked})Overridepublic JsonDeserializer? createContextual(DeserializationContext ctxt, BeanProperty property)throws JsonMappingException {JavaType type  property.getType();// 如果是容器则返回容器内部枚举类型while (type.isContainerType()) {type  type.getContentType();}return new EnumJsonDeSerializer((Class? extends IDictEnum) type.getRawClass());}
} 
3、序列化方法EnumJsonSerializer 
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class EnumJsonSerializer extends JsonSerializerIDictEnum {public void serialize(IDictEnum iDictEnum, JsonGenerator generator, SerializerProvider provider) throws IOException, JsonProcessingException {// 序列化只要code的值generator.writeNumber(iDictEnum.code());// 序列化形式: {code: , desc: }//generator.writeStartObject();//generator.writeNumberField(code, iBaseDict.code());//generator.writeStringField(desc, iBaseDict.desc());//generator.writeEndObject();}
} 
经验证以下这几种情况都能很好的识别成功 
Data
public class AmcNeighInfoPageReq {private AmcManagementModeDictEnum managementMode;private ListAmcManagementModeDictEnum managementModeList;private AmcNeighInfoPageReq amcNeighInfoPageReq;private MapInteger, AmcManagementModeDictEnum map1;private MapAmcManagementModeDictEnum, Integer map2;
} 4.4.mybatis枚举序列化/反序列化处理 
以上两种方法对于mybatis来说没有起到作用需要单独进行mybatis自定义序列化 MyBatis内置了两个枚举转换器分别是org.apache.ibatis.type.EnumTypeHandler和org.apache.ibatis.type.EnumOrdinalTypeHandler。 
EnumTypeHandler是默认的枚举转换器该转换器将枚举实例转换为实例名称的字符串。比如有个枚举。 
例如 前端输入1的话则后端insert的时候的值是 
字符串“UNIFIED_AUTHORIZATION_MANAGEMENT” 
Getter
Accessors(fluent  true)
AllArgsConstructor
public enum AmcManagementModeEnum implements IDictEnum {UNIFIED_AUTHORIZATION_MANAGEMENT( 1, 统一授权管理),//SEMI_AUTHORIZED_MANAGEMENT(2, 半授权管理),INDEPENDENT_MANAGEMENT(3, 独立管理),;/*** 字典码值*/private Integer code;/*** 字典描述*/private String desc;
} 
EnumOrdinalTypeHandler这个转换器将枚举实例的ordinal属性作为取值从0依次取值。还是上面的例子用这种转换器保存在数据库中的值就是0。 
如果我们想保存枚举本身所定义的code值呢这就需要自定义一个类型转换器自定义一个int类型保存在数据库即insert时枚举转换为int型数据保存在数据库select时数据库中的int值转换成实体类的枚举类型。 
4.4.1.TypeHandler 
TypeHandler顾名思义类型转换器就是将数据库中的类型与Java中的类型进行相互转换的处理器。 
经常自定义类型转换器方式有两种实现 TypeHandler 接口 或继承抽象类 BaseTypeHandle并且可以指定转换后的字段类型。 
其实BaseTypeHandler也是继承了TypeHandler接口在实现的TypeHandler接口的方法中调用的是自身抽象方法 
抽象类BaseTypeHandler的抽象方法 
// 执行之前将Java类型转换为对应的jdbc类型用于赋值sql中参数
public abstract void setNonNullParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;
// 根据列名从resultSet中获取将JDBC类型转换为Java类型
public abstract T getNullableResult(ResultSet var1, String var2) throws SQLException;
// 根据下标从resultSet中获取将JDBC类型转换为Java类型
public abstract T getNullableResult(ResultSet var1, int var2) throws SQLException;
// 用于在执行完存储过程后将JDBC类型转换为Java类型
public abstract T getNullableResult(CallableStatement var1, int var2) throws SQLException; 
4.4.2.配置步骤 
1、mybatis自定义枚举类型转换 这里需要配置MappedTypes 
import com.leelen.scd.base.common.util.EnumUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;MappedTypes({IDictEnum.class})
public class EnumTypeHandlerE extends Enum?  IDictEnum extends BaseTypeHandlerIDictEnum {private ClassE type;public EnumTypeHandler(ClassE type) {if (type  null) {throw new IllegalArgumentException(Type argument cannot be null.);}this.type  type;}/*** 用于定义设置参数时该如何把Java类型的参数转换为对应的数据库类型*/Overridepublic void setNonNullParameter(PreparedStatement ps, int i, IDictEnum parameter, JdbcType jdbcType)throws SQLException {ps.setInt(i, parameter.code());}/*** 用于定义通过字段名称获取字段数据时如何把数据库类型转换为对应的Java类型*/Overridepublic E getNullableResult(ResultSet rs, String columnName) throws SQLException {int code  rs.getInt(columnName);return rs.wasNull() ? null : codeOf(code);}/*** 用于定义通过字段索引获取字段数据时如何把数据库类型转换为对应的Java类型*/Overridepublic E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {int code  rs.getInt(columnIndex);return rs.wasNull() ? null : codeOf(code);}/*** 用定义调用存储过程后如何把数据库类型转换为对应的Java类型*/Overridepublic E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {int code  cs.getInt(columnIndex);return cs.wasNull() ? null : codeOf(code);}private E codeOf(int code) {try {return EnumUtil.getEnumByCode(type, code);} catch (Exception ex) {throw new IllegalArgumentException(Cannot convert   code   to   type.getSimpleName()   by code value., ex);}}
} 
这里用到了工具类 
public class EnumUtil {/*** 根据code获取枚举*/public static T extends IDictEnum T getEnumByCode(ClassT tClass, Integer code) {if (code ! null) {for (T t : tClass.getEnumConstants()) {if (t.code().equals(code)) {return t;}}}return null;}
} 
2、定义mybatis的typeHandler扫描包路径 
# mybatis配置参数
mybatis:# 定义typeHandler扫描包路径type-handlers-package: com.leelen.scd 
5.IDEA2019取消枚举提示 
IDEA2019枚举自带入参提示个人感觉看的比较眼花建议把他取消掉。 Settings - Editor - Inlay Hints - Java 选择Parameter hints取消勾选Enum constants 效果如下 6.查看枚举调用的地方 
我们通常使用 ctrl  鼠标左键来查看方法被哪些地方调用但是枚举却没法这么使用。 
解决方法使用alt  F7 来间接查看调用的地方或者右键选择Find Usage 或者使用快捷键 ctl  alt  F7 也可以在idea配置提示