Spring 3.x自动将枚举的ordinal值转换为枚举类型

Spring MVC会自动将前台表单中的数据转换为JavaBean,默认情况下如果JavaBean中使用枚举类型的话,会将枚举的name自动转换为枚举类型,这一点是通过系统自带的org.springframework.core.convert.support.StringToEnumConverterFactory类型转换器来实现的,可以参考这个类来实现将ordinal转换为枚举类型。

在Spring 3.x之前通常使用PropertyEditor来实现数据的类型转换,3.x开始可以使用实现了SPI接口的类型转换系统(如Converter等)来进行转换。PropertyEditor通常用在对表单进行单独进行处理的场合,而类型转换系统适用于批量和通用的场合,我们这里想将所有的枚举类型的ordinal值转换为枚举类型,因此采用类型转换器的方式。

在Spring MVC 3.x中有三种类型转换系统的实现接口:(1)Converter类型转换器接口,只能实现单一的从一种类型S转换为另一种类型T,但不能进行多类型转换或子类型转换,我们这里因为要实现所有的枚举类型自动转换,因此这种方式不适合;(2)GenericConverter和ConditionalGenericConverter接口,前者可以实现多种类型之间的转换,后者同时还可以在特定条件下实现多种功能类型转换,但二者都不能实现所有子类型的转换;(3)ConverterFactory 工厂模式的接口,用于指定Converter即转换器,但提供了三种类型:S源类型、R目标类型的父类型、T目标类型且为R类型的子类型,这种方式非常适合我们,因此我们采用这种方式,代码如下:

public class OrdinalToEnumConverterFactory implements ConverterFactory> {

@Override
public > Converter getConverter(Class targetType) {
return new OrdinalToEnum(targetType);
}

private class OrdinalToEnum> implements Converter {

private final Class enumType;

public OrdinalToEnum(Class enumType) {
this.enumType = enumType;
}

@Override
public T convert(String source) {
// 转换成数字
int ordinal = Numbers.toInt(source, Integer.MIN_VALUE);
if(ordinal == Integer.MIN_VALUE) {
return null;
}
return Enums.valueOf(enumType, ordinal);
}

}
}

其中Enums.valueOf方法可以自己实现,思路是首先通过Enum Class的getEnumConstants方法获取所有的枚举类型的数组,然后使用ordinal索引号进行自动匹配,需要注意溢出的情况。

做完了上面的工作之后还需要在配置文件中进行定义和引入,配置片段如下:






虽然官方文档中说只要将bean的id设置成conversionService就会自动启用,但是我测试下来还需要在mvc:annotation-driven中使用conversion-service进行调用才有效。

参考资料:
Spring custom converter for all Enums
Spring MVC type conversion : PropertyEditor or Converter?
SpringMVC数据类型转换
Spring Doc ConverterFactory

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注