в нашем проекте мы определяем перечисления как ниже
public enum GenderEnum implements IEnum{
MALE(1),
FEMALE(2);
private Integer code;
GenderEnum(int code) {
this.code = code;
}
public static GenderEnum getByCode(int code) {
for (GenderEnum genderEnum : values()) {
if (genderEnum.code == code) {
return genderEnum;
}
}
return null;
}
}
мы хотим использовать эти перечисления в классах, используемых для параметров, как
public class Param{
String id;
GenderEnum gender;
}
у нас есть контроллеры как
@RestController
class MyController{
@PostMapping('/alink')
ResponseBean doSomething(@RequestBody Param param){
...
}
}
для приведенного выше случая, когда тело запроса равно
{"id":"L323", "gender":1}
, мы надеемся, 1
можно преобразовать в перечисление MALE
Одно из решений заключается в добавлении @JsonCreator
over getByCode(int code)
utНо в нашем существующем проекте слой хранилища преобразует enum в его строковое значение (MALE
или FEMALE
), но не в значение code
перед вставкой их в базу данных. Поэтому, если мы добавим @JsonCreator
сверх getByCode(int code)
, мы столкнемся с ошибками при попытке извлечь перечисления из базы данных.
как мы можем заставить mvc / controller преобразовать целочисленное значение входных данных в enum, не затрагивая слой хранилища?
Я вижу решение, как показано ниже:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new EnumConverterFactory());
}
}
static class EnumConverterFactory implements ConverterFactory<Integer, IEnum> {
@Override
public <T extends IEnum> Converter<Integer, T> getConverter(Class<T> targetType) {
if (!targetType.isEnum()) {
throw new UnsupportedOperationException(targetType + "is not enum");
}
return new EnumConverter(targetType);
}
private static class EnumConverter<T extends IEnum> implements Converter<Integer, T> {
private final Class<T> enumType;
public EnumConverter(Class<T> enumType) {
this.enumType = enumType;
}
@Override
public T convert(Integer code) {
for (T t : enumType.getEnumConstants()) {
if (code.equals(t.getCode())) {
return t;
}
}
return null;
}
}
}
, ноэто решение не работает. При отладке я замечаю, что разрешение параметра зависит от сериализации Джексона (которая преобразует целое число в enum согласно порядковому номеру вместо значения кода), и преобразователь просто не задействован.
Итак, есть ли обходной путь?