«Это 25-й день моего участия в ноябрьском испытании обновлений. Ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Эта статья была«Реальный бой весеннего ботинка»Коллекция столбцов.
Привет, я смотрю на гору.
В процессе разработки интерфейса неизбежно появляются параметры, представляющие типы, такие как 0 для неизвестного, 1 для мужчины и 2 для женщины. Обычно есть два способа сделать это: один представлен числами, а другой реализуется с помощью перечислений.
Использование цифрового представления заключается в согласовании значения каждого цифрового представления в форме контракта.Когда интерфейс получает параметры, он оценивает тип в соответствии с соглашением, а стоимость обслуживания интерфейса относительно высока.
В системе Spring использование представления перечисления заключается в использовании механизма преобразования Spring, который может сопоставлять числа или строки с серийным номером или именем перечисления, а затем преобразовывать входные данные внешнего интерфейса в тип перечисления.
В сценариях, где сцена несложная, перечисление может легко выполнить эту работу.
Итак, быстро внедряйте логику и готовьтесь к тестированию. В настоящее время требования изменились. Нельзя выбрать неизвестный пол. Можно выбрать только мужчину или женщину, и нет значения 0. Таким образом, поскольку значение начинается с 1, а порядковый номер перечисления начинается с 0, возникнет конфликт.
Есть также некоторые не слишком много сценариев, то есть внешний интерфейс не ожидает, что типы будут числами, и может ожидать, что они будут представлены некоторыми значимыми строками. Однако, согласно спецификации внешнего интерфейса, его имя должно быть написано в нижнем или верблюжьем регистре. Но во внутренней спецификации перечисления должны быть написаны с заглавной буквы, что является конфликтом.
Независимо от того, разумен спрос или нет, мы должны сохранять дух исследования технологий.
Подтвердить потребности
Сначала подтвердите потребности. Ждем определения класса перечисления в качестве параметра.При обращении к интерфейсу это может быть идентификатор типа int.Значение идентификатора не ограничено количеством перечислений или тип String,код,значение кода не ограничено. к перечисляемому Имени. Другими словами, это перечисление имеет идентификатор и код, определяемые свободно, пока передается интерфейс, он может быть автоматически преобразован в тип перечисления.
В таком случае давайте стандартизируем значения id и code. Для расширения определите три интерфейса: IdBaseEnum, CodeBaseEnum и IdCodeBaseEnum.
public interface IdBaseEnum {
Integer getId();
}
public interface CodeBaseEnum {
String getCode();
}
public interface IdCodeBaseEnum extends IdBaseEnum, CodeBaseEnum {
}
Теперь пришло время определить нашего главного героя.
определить перечисление
Впереди определены три интерфейса: отдельный идентификатор, отдельный код и один с идентификатором и кодом. Таким образом, мы можем определить три перечисления, соответствующие трем интерфейсам. Все три метода похожи, поэтому в тексте они не повторяются. Если вам интересно, вы можете обратить внимание на паблик «Дом в горах» и ответить на него, чтобы получить исходный код.
Мы определяем гендерное перечисление с двумя свойствами: id и code.
public enum GenderIdCodeEnum implements IdCodeBaseEnum {
MALE(1, "male"),
FEMALE(2, "female");
private final Integer id;
private final String code;
GenderIdCodeEnum(Integer id, String code) {
this.id = id;
this.code = code;
}
@Override
public String getCode() {
return code;
}
@Override
public Integer getId() {
return id;
}
}
Следует отметить, что идентификатор и код не могут повторяться.
- id и id, code и code не могут повторяться. Например, MAIL определяет id как 1, а FAMLE не может определять id как 1.
- Идентификатор и код не могут повторяться. Например, MALE определяет идентификатор как 1001, а FEMALE определяет код как 1001.
Это связано с тем, что Spring обрабатывает все входные параметры как типы String при преобразовании параметров. Хотя мы определяем разные типы идентификатора и кода, при сопоставлении все они сопоставляются в соответствии со строками. Если одно и то же значение существует, возникает неоднозначность.
Преобразователи и ConverterFactory
Далее согласно спецификации определим Converter и ConverterFactory. Это порты расширения, которые оставляет нам Spring, и их можно определить в соответствии со спецификацией.
Класс преобразователя:
public class IdCodeToEnumConverter<T extends IdCodeBaseEnum> implements Converter<String, T> {
private final Map<String, T> idEnumMap = Maps.newHashMap();
private final Map<String, T> codeEnumMap = Maps.newHashMap();
public IdCodeToEnumConverter(Class<T> enumType) {
Arrays.stream(enumType.getEnumConstants())
.forEach(x -> {
idEnumMap.put(x.getId().toString(), x);
codeEnumMap.put(x.getCode(), x);
});
}
@Override
public T convert(String source) {
return Optional.of(source)
.map(codeEnumMap::get)
.orElseGet(() -> Optional.of(source)
.map(idEnumMap::get)
.orElseThrow(() -> new CodeBaseException(ErrorResponseEnum.PARAMS_ENUM_NOT_MATCH)));
}
}
Класс ConverterFactory:
public class IdCodeToEnumConverterFactory implements ConverterFactory<String, IdCodeBaseEnum> {
@SuppressWarnings("rawtypes")
private static final Map<Class, Converter> CONVERTERS = Maps.newHashMap();
@Override
public <T extends IdCodeBaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
//noinspection unchecked
Converter<String, T> converter = CONVERTERS.get(targetType);
if (converter == null) {
converter = new IdCodeToEnumConverter<>(targetType);
CONVERTERS.put(targetType, converter);
}
return converter;
}
}
Эти два являются ядром преобразования.Мы можем реализовать автоматическое преобразование типов перечисления, собрав их в преобразователь типов Spring.
загрузить конфигурацию
Зарегистрируйте наши определенные Converter и ConverterFactory с помощью преобразователя типов Spring.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new IdCodeToEnumConverterFactory());
registry.addConverterFactory(new CodeToEnumConverterFactory());
registry.addConverterFactory(new IdToEnumConverterFactory());
}
}
На этом основные определения закончены.
контрольная работа
Напишите Controller в качестве тестовой записи:
@RestController
@RequestMapping("echo")
public class EchoController {
@GetMapping("gender-id-code")
public String genderIdCode(@RequestParam("gender") GenderIdCodeEnum gender) {
return gender.name();
}
}
Подготовьте тестовый пример для тестирования:
@SpringBootTest(classes = SpringEnumParamApplication.class)
@AutoConfigureMockMvc
class EchoControllerTest {
@Autowired
private MockMvc mockMvc;
@ParameterizedTest
@ValueSource(strings = {"MALE", "male", "1"})
void genderIdCode(String gender) throws Exception {
final String result = mockMvc.perform(
MockMvcRequestBuilders.get("/echo/gender-id-code")
.param("gender", gender)
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse()
.getContentAsString();
Assertions.assertEquals("MALE", result);
}
}
Вывод в конце статьи
Реализовать параметры перечисления несложно, если оно реализовано в соответствии со спецификацией расширения Spring. Важно обратить внимание на уникальный идентификатор и код в классе enum.
Эта статья приложения, в следующей статье будет говорить о принципе. И логика преобразования enum для запросов в виде http body. Ответьте на «весну» на официальном аккаунте «Глядя на хижину горы», чтобы получить исходный код. Три формы перечисления полностью определены в исходном коде.
Рекомендуемое чтение
- SpringBoot Combat: элегантный ответ для достижения результата
- Борьба с SpringBoot: как изящно обрабатывать исключения
- Бои SpringBoot: динамическая инъекция генератора идентификаторов через BeanPostProcessor
- SpringBoot Combat: пользовательский фильтр элегантно получает параметры запроса и результаты ответа
- Бои SpringBoot: элегантное использование параметров перечисления
- Бои SpringBoot: элегантное использование параметров перечисления (принцип)
- Спрингбат бой: элегантное использование параметров перечисления в запросе
- Бой SpringBoot: элегантное использование параметров перечисления в RequestBody (принцип)
- SpringBoot бой: JUnit5+MockMvc+Mockito проводят модульное тестирование
- SpringBoot бой: загрузка и чтение содержимого файла ресурсов
Привет, я смотрю на гору. Плавайте в мире кода, играйте и наслаждайтесь жизнью. Если статья была вам полезна, ставьте лайк, добавляйте в закладки и подписывайтесь. Приглашаем обратить внимание на паблик-аккаунт «Глядя на горную хижину» и открыть для себя другой мир.