WebDataBinder枚举类型转换
WebDataBinder
依赖于Converter实现类型转换,若Controller方法声明的@RequestParam
参数的类型不是String
,WebDataBinder
就会自动进行数据类型转换。SpringMVC提供了常用类型的转换器,例如String
到Integer
、String
到Date
,String
到Boolean
等等,其中也包括String
到枚举类型,但是String
到枚举类型的默认转换规则是根据实例名称("APARTMENT")转换为枚举对象实例(ItemType.APARTMENT)。若想实现code
属性到枚举对象实例的转换,需要自定义Converter
,代码如下,具体内容可参考官方文档。
@Component
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);
}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private StringToItemtypeConverter stringToItemTypeConverter;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(this.stringToItemTypeConverter);
}
}
但是我们有很多的枚举类型都需要考虑类型转换这个问题,按照上述思路,我们需要为每个枚举类型都定义一个Converter,并且每个Converter的转换逻辑都完全相同,针对这种情况,我们使用ConverterFactory接口更为合适,这个接口可以将同一个转换逻辑应用到一个接口的所有实现类,因此我们可以定义一个BaseEnum
接口,然后另所有的枚举类都实现该接口,然后就可以自定义ConverterFactory
,集中编写各枚举类的转换逻辑了。具体实现如下:
在model模块定义com.atguigu.lease.model.enums.BaseEnum
接口
public interface BaseEnum {
Integer getCode();
String getName();
}
令所有com.atguigu.lease.model.enums
包下的枚举类都实现BaseEnun
接口
@Component
public class StringToBaseEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
@Override
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);
}
};
}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
//@Autowired
// private StringToItemtypeConverter stringToItemTypeConverter;
@Autowired
private StringToBaseEnumConverterFactory stringToBaseEnumConverterFactory;
@Override
public void addFormatters(FormatterRegistry registry) {
// registry.addConverter(this.stringToItemTypeConverter);
registry.addConverterFactory(stringToBaseEnumConverterFactory);
}
}