Spring的枚举类转换器有StringToEnumConverterFactoryIntegerToEnumConverterFactory,根据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())
    }
}

参考文章:https://zhuanlan.zhihu.com/p/147882901

最后修改:2022 年 03 月 04 日
如果觉得我的文章对你有用,请随意赞赏