相信大家在作项目时肯定遇到过参数转换问题!尤其是初学者,也会困惑,知其然,不知其所以然后!
在web场景下,接收一些参数一般会加一些注解:
比如@Param、@RequestBody、@RequestHeader、@RequestParam等
其中@RequestBody是这篇的主角儿
1、@ResponseBody 由 HttpMessageConverter处理
进行内容协商 :
可给客户端(多端)返回特定的格式:JSON、XML、YAML等多种
今天这里基于JSON格式,也是比较常用的格式,来解决String转换枚举类型!
1、转换过程分两大过程:
a、前端与后端的类型转换
b、后端与数据库的类型转换
材料来源尚硅谷项目
## 请求流程

A:前端与后端的数据转换:
由WebDataBinder进行参数绑定,并实现转换。
方法接参:
public Result<List<LabelInfo>> labelList(@RequestParam(required = false) ItemType type) {...}
但是前端传入的参数均是文本,即字符串类型。转Integer、Float、Object、Blooean等都能自动实现,但自定义的“枚举类型”则得不到想要的结果,如下枚举:
那个BaseEnum是一些get方法不用管
public enum ItemType implements BaseEnum {
APARTMENT(1, "公寓"),
ROOM(2, "房间");
@EnumValue
@JsonValue
private Integer code;
private String name;
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getName() {
return name;
}
ItemType(Integer code, String name) {
this.code = code;
this.name = name;
}
}
在接口想要将type="1" 转成对应的ItemType实例即APARTMENT
需要自定义Converter:
@Component
public class StringToBaseEnumConverter implements ConverterFactory<String, BaseEnum> {
//可以实现String类型向BaseEnum的子类转换
//当SpringMVC需要某个类型的converter时,底层会自己调用下面的方法,传入目标类型的class
//最关键:SpringBoot会自动将需要的子枚举类对象传入getConverter里
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return code -> {
T[] enumConstants = targetType.getEnumConstants(); //拿到目标枚举的全部实例
for (T enumConstant : enumConstants) { //遍历哪个实例是匹配的上传来的code
if (enumConstant.getCode().equals(Integer.parseInt(code))) {
return enumConstant;
}
}
throw new IllegalArgumentException("code:非法"+code);
};
}
}
1、需要实现ConverterFactory接口,里面的参数String --->BaseEnum的子类ItemType转换
2、这里使用的转换器工厂,便于动态映射到需要转换的枚举类上
3、因为上面接口传参是ItemType,即告诉SpringBoot需要BaseEnum转换成ItemType,拿到后,需要去ItemType里面的实例,即APARTMENT、ROOM等,
4、最关键的是需要:属性值code与实列映射上,回应为啥前端传个“1”能映射上ItemType的APARTMENT实列上呢?你说对吧!
5、属性值与实例映射上面代码解释了
处理好转换工厂后,还需要将其注册到Spring中,被SpringMVC感知,需要在配置类:
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private StringToBaseEnumConverter stringToBaseEnumConverter;
//自定义converter需要被SpringMVC感知
@Override
public void addFormatters(FormatterRegistry registry) {
//使用注册方法,自定义converterFactory
registry.addConverterFactory(this.stringToBaseEnumConverter); //或者new一个
}
}
做好这一些就映射上了,但是....
B:后端与数据库的类型转换
由TypeHandler处理,使用一个@EnumValue处理转换
Mybatis预置的TypeHandler可以处理常用的数据类型转换,例如String、Integer、Date等等,其中也包含枚举类型,但是枚举类型的默认转换规则是枚举对象实例(ItemType.APARTMENT)和实例名称("APARTMENT")相互映射。若想实现code属性到枚举对象实例的相互映射,需要自定义TypeHandler。
不过MybatisPlus提供了一个通用的处理枚举类型的TypeHandler。其使用十分简单,只需在ItemType枚举类的code属性上增加一个注解@EnumValue,Mybatis-Plus便可完成从ItemType对象到code属性之间的相互映射,具体配置如下。
public enum ItemType {
APARTMENT(1, "公寓"),
ROOM(2, "房间");
@EnumValue
private Integer code;
private String name;
ItemType(Integer code, String name) {
this.code = code;
this.name = name;
}
}
响应流程:

上面的步骤在返回给前端时,只能返回实例名称“APARTMENT”
解决:
在上面的枚举类添加一个@JsonValue,进行反序列化,第一个代码有
HTTPMessageConverter枚举类型转换
HttpMessageConverter依赖于Json序列化框架(默认使用Jackson)。其对枚举类型的默认处理规则也是枚举对象实例(ItemType.APARTMENT)和实例名称("APARTMENT")相互映射。不过其提供了一个注解@JsonValue,同样只需在ItemType枚举类的code属性上增加一个注解@JsonValue,Jackson便可完成从ItemType对象到code属性之间的互相映射。具体配置如下,详细信息可参考Jackson官方文档。
这里描述是尚硅谷项目文档提供的!
@EnumValue 与 @JsonValue
@EnumValue: 由MybatisPlus提供
@JsonValue: 由HTTPMessageConverter提供,将code属性反序列化成枚举实例
作用都是将枚举实例与code属性相互映射
以上问题在处理数据类型转换都能的到解决,当然也可以参考官方文档!

880





