Spring
的枚举类转换器有StringToEnumConverterFactory
和IntegerToEnumConverterFactory
,根据Spring
官方的说法(https://github.com/spring-projects/spring-framework/issues/25543),Get
请求收到的都是字符串,即使是数字字符串,也会使用StringToEnumConverterFactory
,这就导致提交枚举类的ordinal
值会出现400
错误,IntegerToEnumConverterFactory
不用于web
请求参数场景。
那么只能重写StringToEnumConverterFactory
,在收到的不为数字字符串,使用枚举类的name
来进行转换,收到的为数字字符串,使ordinal
来转换,代码如下:
class StringToEnumConverterFactory: ConverterFactory<String, Enum<*>> {
override fun <T : Enum<*>?> getConverter(targetType: Class<T>): Converter<String, T> {
val ss = StringToEnum()
ss.enumType = getEnumType(targetType) as? Class<Enum<*>>
return ss as Converter<String, T>
}
private fun getEnumType(targetType: Class<*>?): Class<*> {
var enumType = targetType
while (enumType != null && !enumType.isEnum) {
enumType = enumType.superclass
}
Assert.notNull(enumType, "The target type ${targetType?.name} does not refer to an enum")
return enumType!!
}
private class StringToEnum<T: Enum<*>>: Converter<String, T> {
var enumType: Class<T>? = null
override fun convert(source: String): T? {
val ordinal = source.toIntOrNull()
return if (ordinal == null) {
if (source.isEmpty()) null
else {
enumType?.enumConstants?.find { it.name == source } as T
}
} else
enumType?.enumConstants?.get(ordinal)
}
}
}
// 如果为SpringMvc,应该实现WebMvcConfigurer接口
@Component
class MyConfig: WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
super.addFormatters(registry)
registry.addConverterFactory(StringToEnumConverterFactory())
}
}