Автор оригинала: Alejandro Ugarte.
1. Обзор
Когда дело доходит до проверки пользовательского ввода, Spring Boot обеспечивает мощную поддержку этой распространенной, но важной задачи прямо из коробки.
Хотя Spring Boot поддерживает бесшовную интеграцию с пользовательскими валидаторами, фактическим стандартом для выполнения валидации является Hibernate Validator , эталонная реализация Bean Validation framework.
В этом уроке мы рассмотрим, как проверить объекты домена в Spring Boot .
Дальнейшее чтение:
Источник настраиваемого сообщения проверки в весенней загрузке
Разница между ограничениями @NotNull, @NotEmpty и @NotBlank при проверке компонентов
2. Зависимости Maven
В этом случае мы узнаем, как проверить объекты домена в Spring Boot , создав базовый контроллер СБРОСА.
Контроллер сначала примет объект домена, затем проверит его с помощью валидатора Hibernate и, наконец, сохранит его в базе данных H2 в памяти.
Зависимости проекта довольно стандартны:
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 1.4.197 runtime
Как показано выше, мы включили spring-boot-starter-web в ваш pom.xml файл, потому что он нам понадобится для создания контроллера REST. Кроме того, давайте обязательно проверим последние версии spring-boot-starter-jpa и базу данных H2 на Maven Central.
Начиная с Boot 2.3, нам также необходимо явно добавить зависимость spring-boot-starter-validation :
org.springframework.boot spring-boot-starter-validation
3. Простой Доменный Класс
Поскольку зависимости вашего проекта уже существуют, далее нам нужно определить пример класса сущностей JPA, роль которого будет заключаться исключительно в моделировании пользователей.
Давайте взглянем на этот класс:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; // standard constructors / setters / getters / toString }
Реализация нашего класса User entity действительно довольно анемична, но она в двух словах показывает, как использовать ограничения проверки бобов для ограничения полей name и email .
Для простоты мы ограничили целевые поля, используя только ограничение @NotBlank . Кроме того, мы указали сообщения об ошибках с атрибутом message .
Поэтому, когда Spring Boot проверяет экземпляр класса, ограниченные поля не должны быть нулевыми, а их обрезанная длина должна быть больше нуля .
Кроме того, проверка Bean предоставляет множество других удобных ограничений, помимо @NotBlank. Это позволяет нам применять и комбинировать различные правила проверки для ограниченных классов. Для получения дополнительной информации, пожалуйста, ознакомьтесь с официальными документами по проверке бобов .
Поскольку мы будем использовать Spring Data JPA для сохранения пользователей в базе данных H2 в памяти, нам также необходимо определить простой интерфейс репозитория для базовой функциональности CRUD на объектах User :
@Repository public interface UserRepository extends CrudRepository{}
4. Реализация контроллера REST
Конечно, нам нужно реализовать слой, который позволяет нам получать значения, присвоенные ограниченным полям нашего Пользователя объекта.
Поэтому мы можем проверить их и выполнить еще несколько задач, в зависимости от результатов проверки.
Spring Boot делает этот, казалось бы, сложный процесс действительно простым благодаря реализации контроллера REST.
Давайте рассмотрим реализацию контроллера REST:
@RestController public class UserController { @PostMapping("/users") ResponseEntityaddUser(@Valid @RequestBody User user) { // persisting the user return ResponseEntity.ok("User is valid"); } // standard constructors / other methods }
В контексте Spring REST реализация метода addUser() довольно стандартна.
Конечно, наиболее важной частью является использование аннотации @Valid .
Когда Spring Boot находит аргумент с аннотацией @Действительный , он автоматически загружает реализацию JSR 380 по умолчанию — Hibernate Validator — и проверяет аргумент.
Когда целевой аргумент не проходит проверку, Spring Boot создает исключение MethodArgumentNotValidException .
5. Аннотация @ExceptionHandler
Хотя очень удобно, чтобы Spring Boot автоматически проверял объект User , передаваемый методу addUser () , недостающий аспект этого процесса заключается в том, как мы обрабатываем результаты проверки.
@ExceptionHandler аннотация позволяет нам обрабатывать определенные типы исключений с помощью одного метода.
Поэтому мы можем использовать его для обработки ошибок проверки:
@ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public MaphandleValidationExceptions( MethodArgumentNotValidException ex) { Map errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return errors; }
Мы указали MethodArgumentNotValidException исключение как исключение, которое должно быть обработано . Следовательно, Spring Boot вызовет этот метод , когда указанный объект User недопустим .
Метод сохраняет имя и сообщение об ошибке после проверки каждого недопустимого поля в карте. Затем он отправляет Map обратно клиенту в виде представления JSON для дальнейшей обработки.
Проще говоря, контроллер REST позволяет нам легко обрабатывать запросы к различным конечным точкам, проверять объекты User и отправлять ответы в формате JSON.
Дизайн достаточно гибок, чтобы обрабатывать ответы контроллера через несколько веб-уровней , начиная от движков шаблонов, таких как Thymeleaf , и заканчивая полнофункциональным фреймворком JavaScript, таким как Angular .
6. Тестирование контроллера REST
Мы можем легко протестировать функциональность нашего контроллера REST с помощью интеграционного теста .
Давайте начнем издеваться над/автозапуском реализации интерфейса UserRepository вместе с экземпляром UserController и объектом MockMvc :
@RunWith(SpringRunner.class) @WebMvcTest @AutoConfigureMockMvc public class UserControllerIntegrationTest { @MockBean private UserRepository userRepository; @Autowired UserController userController; @Autowired private MockMvc mockMvc; //... }
Поскольку мы тестируем только веб-слой, мы используем аннотацию @WebMvcTest . Это позволяет нам легко тестировать запросы и ответы, используя набор статических методов, реализованных классами MockMvcRequestBuilders и MockMvcResultMatchers .
Теперь давайте протестируем метод addUser() с допустимым и недопустимым объектом User , переданным в теле запроса:
@Test public void whenPostRequestToUsersAndValidUser_thenCorrectResponse() throws Exception { MediaType textPlainUtf8 = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")); String user = "{\"name\": \"bob\", \"email\" : \"[email protected]\"}"; mockMvc.perform(MockMvcRequestBuilders.post("/users") .content(user) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content() .contentType(textPlainUtf8)); } @Test public void whenPostRequestToUsersAndInValidUser_thenCorrectResponse() throws Exception { String user = "{\"name\": \"\", \"email\" : \"[email protected]\"}"; mockMvc.perform(MockMvcRequestBuilders.post("/users") .content(user) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(MockMvcResultMatchers.status().isBadRequest()) .andExpect(MockMvcResultMatchers.jsonPath("$.name", Is.is("Name is mandatory"))) .andExpect(MockMvcResultMatchers.content() .contentType(MediaType.APPLICATION_JSON_UTF8)); } }
Кроме того, мы можем протестировать API контроллера СБРОСА с помощью бесплатного приложения для тестирования жизненного цикла API , такого как Postman .
7. Запуск примера приложения
Наконец, мы можем запустить наш пример проекта со стандартным методом main() :
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner run(UserRepository userRepository) throws Exception { return (String[] args) -> { User user1 = new User("Bob", "[email protected]"); User user2 = new User("Jenny", "[email protected]"); userRepository.save(user1); userRepository.save(user2); userRepository.findAll().forEach(System.out::println); }; } }
Как и ожидалось, мы должны увидеть пару объектов User , распечатанных в консоли.
Запрос на публикацию в http://localhost:8080/users конечная точка с допустимым Пользователем объектом вернет Строку “Пользователь допустим”.
Аналогично, запрос POST с Пользователем объектом без имени и электронной почты значений вернет следующий ответ:
{ "name":"Name is mandatory", "email":"Email is mandatory" }
8. Заключение
В этой статье мы изучили основы выполнения проверки в Spring Boot .
Как обычно, все примеры, показанные в этой статье, доступны на GitHub .