一、优雅对接前端
前言
本人以前写代码,对于一些比如状态,是否默认,是否删除等字段时,通常会在建表时添加注释,然后和前端约定数据意义。
但工作久了就会发现,有时候和前端约定起来会很麻烦,当我想要再添加一个新状态时,仍需要和前端沟通同步。
而且在写业务代码是,大量的魔法值总是让人不爽,而且容易混淆,尽管可以定义常量类去代表某一个状态,但总是不够直观。
之前就有了解过枚举类的作用,就考虑使用枚举类,对所有该类型的数据进行封装。
枚举类的创建
封装时,首先面临的问题是枚举类的创建
由于每张表中的常量代表的意义都不一样,所以对于不同意义的常量,都要定义一个枚举类
由于枚举类不能继承,所以能封装的内容比较有限。尽管这些常量内容字段都是统一的,但在每个枚举类中仍要定义:
初始的枚举类:
/**
* @author jeff
* @since 2023/4/30 17:46
*/
public enum UserStatus{
DISABLE(0,"禁用"),
ENABLE(1,"启用");
@Getter
private int value;
@Getter
private String desc;
UserStatus(int value, String desc){
this.value=value;
this.desc=desc;
}
}
需要考虑的问题
由于枚举类的内容是在首次加载时就初始化好了的,所以比对的时候直接equals就好了。
这时的问题是,equals时,另一个用于比对的数据是怎么来的?
既然使用了枚举的方式处理常量,那么自己存枚举类进实体类的情况就不能出现在业务代码中。
这里能考虑到的数据来源则有
前端传递的数据,数据库中获取的数据。
问题处理
前端数据处理-接收(有坑)
前端传递的数据,我最开始认为是需要写convertor进行转换的。
但新版的Spring MVC已经将枚举的转换处理好了,前端只要传递常量值,MVC就能将对应的枚举封装进实体类中。
MVC使用ordinal处理参数
但是!MVC是对枚举的ordinal进行数据处理的!所以会有坑
这里就要提到java中,枚举类数据是首次加载类时初始化的,而且是按顺序的,最后会形成一个数组。
而其ordinal方法,则是返回该枚举在数组中的索引位的,而且最关键的是,该方法被final修饰,也就是说我们无法覆写该方法
样例:
可以看到,前端发送常量数据后,后端接收的数据是经过转换的了
而且如果前端传递的数据在枚举中不存在,则会报400异常。
前端数据处理-返回(非完全处理)
不过测试时可以发现,返回的枚举类型,数据是枚举对象的名称:
这个值要是返回给前端,感觉能直接打起来,所以是肯定不行的。
这个问题是返回数据时,对枚举类型的转换的问题,json化返回数据时,碰到枚举类,会直接输出枚举类的值。
问题解决-返回枚举json:
这时只要在枚举类上加上此注解,让枚举类的参与json化即可解决:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
这时跟前端说好,以后按照这种格式处理常量数据就好
问题解决-返回枚举value:
当然,如果觉得返回的数据太臃肿了,也可以在json化的时候,换种处理类型
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
事实上,如果规范化所有的枚举类的值和ordinal,到这里问题就基本上解决了。
但本文自然是不能止步于此。
可能会出现的问题
看看如果传的值超过了枚举类的ordinal会是什么情况
可以看到SpringMVC不是对值做匹配的
先对本文做个总结吧
SpringMVC有对枚举类进行处理,依靠枚举类的排序值ordinal
如果系统中的这些常量枚举,值和ordinal一致的话,则根据本文即可处理好枚举类型的接收与返回
处理返回,默认返回枚举名称字符串,想要返回枚举数据,需要使用
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
注释枚举类,让枚举类参与json化
想要如果想要返回ordinal的话,则要用到
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
后续文章链接
暂时还没写哈哈