Spring WebFlux Get请求Integer类型转枚举类

kuku 发布于 22 天前 1 次阅读


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

此作者没有提供个人介绍。
最后更新于 2025-09-23