HTTPSMessageConverter:String转换(自定义)枚举类型

相信大家在作项目时肯定遇到过参数转换问题!尤其是初学者,也会困惑,知其然,不知其所以然后!

在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可以处理常用的数据类型转换,例如StringIntegerDate等等,其中也包含枚举类型,但是枚举类型的默认转换规则是枚举对象实例(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属性相互映射

以上问题在处理数据类型转换都能的到解决,当然也可以参考官方文档!

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值