逻辑删除
使用 mybatis-plus-global-logic-field
来实现逻辑删除功能。
前后端通信时忽略的字段
通过 @JsonIgnore
注解来指定前后端通信时需要忽略的字段。
自动填充机制
- 字段填充设置:
利用@TableField(fill=FieldFill.Update)
来标注需要自动填充的字段,指明填充时机(此处为更新时)。 - 填充值规则设置:
实现MetaObjectHandler
接口,并重写insertFill()
和updateFill()
两个方法,以此来定义具体的填充值规则。
枚举类型和数字之间的对应关系设置
- 默认情况:
枚举ItemType
有两个常量值:APARTMENT(1,"公寓")
,ROOM(2,"房间")
。在Java端,若有ItemType
为APARTMENT
,往数据库中保存时,默认是将它的字符串形式"APARTMENT"
保存到对应的列中。但数据库中该列对应的类型是tinyint
,我们希望将1
(也就是ItemType
这个枚举中的code
属性值)保存到这一列中,所以需要使用@EnumValue
在code
属性上标注。 - 前端到后端请求体转换:
在前端,用户选择"公寓"
或"房间"
时,向后端发送的是"1"
或者"2"
。而后端的entity
中的属性类型不是int
,而是ItemType
。因此,需要将前端发送过来的"1"
或者"2"
转化成ItemType
这个类型,此时需要说明请求体中的"1"
或者"2"
到底和ItemType
中的哪个属性对应,请求体中的1
和ItemType
中的code
属性对应,需要使用@JsonValue
。 - 后端到前端响应体转换:
服务器端从数据库中查询出了"1"
,服务器端实体中的属性类型是ItemType
,这个1
依据@EnumValue
给ItemType
中的属性赋值,然后服务器端查询到的数据需要通过响应体响应给前端,ItemType
这个枚举如果直接响应给前端,则是"APARTMENT"
,但我们需要将1
或者2
响应给前端,因此,需要使用@JsonValue
在code
属性上标注。 请求参数相关情况及解决方法:
如果不是请求体,而是请求参数中包含1
或者2
,springmvc
有一个组件WebDataBinder
,它其中一个作用是参数绑定。- WebDataBinder默认处理情况:
WebDataBinder
默认情况下直接处理String
类型的参数,获取前端的数据一定是字符串类型,例如"1"
,如果Java端对应的属性是String
类型,则直接赋值;如果类型不一致,例如获取到参数"1"
,Java端对应的是Integer
,springMVC
内置了常规类型的数据类型转换器(Converter
),可以将String
转换成Integer
。在常规转换规则下,字符串和枚举也可以自动转换(如1
-> 某一个枚举值),不过实际情况是"APARTMENT"
和ItemType
这个枚举之间自动对应,而不是"1"
对应,所以需要自己去实现字符串和枚举之间的转换关系。- 解决方法一(针对单个枚举类):
自定义类实现
Converter
,重写其中的convert
方法,示例代码如下:public class StringToItemTypeConverter implements Converter<String, ItemType> { @Override public ItemType convert(String source) { return Arrays.stream(ItemType.values()) .filter(itemType -> source.equals(itemType.getCode())) .findFirst().orElseThrow(RuntimeException::new); } }
然后通过
WebMvcConfigurer
注册这个转换器,示例代码如下:public class WebMvcConfiguration implements WebMvcConfigurer { public void addFormatter(registry){ registry.addConverter(stringToItemTypeConverter); } }
按照这种解决方式,当前项目中存在很多的枚举类(如
ItemType
、AppointmentStatus
、ReleaseStatus
等),每个枚举类都要对应一个Converter
,然后分别去注册它们。- 解决方法二(通用方案):
使用
ConverterFactory
,示例代码如下:public class StringToBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> { public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) { return new Converter<String, T>() { @Override public T convert(String source) { return Arrays.stream(targetType.getEnumConstants()).filter(t -> source.equals(t.getCode()+"")) .findFirst().orElseThrow(RuntimeException::new); } }; } }