Рубрики
Без рубрики

Проверки в весенней загрузке

Привет! В этой статье я расскажу о проверках в приложении Spring Boot. Единственное требование для йо… Помеченный как java, весна, весенняя загрузка.

Привет! В этой статье я расскажу о проверках в приложении Spring Boot. Единственное требование для понимания этой темы – уметь создавать контроллеры в Spring Boot и, конечно же, быть уверенным в Java.

Вы можете найти исходный код для примеров здесь: https://github.com/kamer/validations-in-spring-boot

Зачем нам нужна проверка как на стороне клиента, так и на стороне сервера?

В веб-приложениях мы обычно используем проверки как на стороне клиента, так и на стороне сервера для данных формы или любых других данных, которые передаются на сторону сервера. Зачем нам беспокоиться о них обоих?

Потому что мы используем проверку на стороне клиента для быстрой проверки и реагирования. Например, у нас есть поле, которое принимает номер телефона. Итак, прежде всего, мы должны запретить пользователю вводить какие-либо символы, кроме цифр. Кроме того, у нас есть шаблон, который проверяет номер телефона. Если мы контролируем и отклоняем любое неверное введенное значение на стороне клиента, мы исключаем время, необходимое для того, чтобы этот запрос прошел на стороне сервера и был отклонен. Таким образом, мы можем сказать, что проверки на стороне клиента в основном используются для быстрой обратной связи с пользователем и проверки синтаксических вещей. ( например, шаблон, длина, символы)

Но проверки на стороне клиента можно считать бесполезными, поскольку ими можно легко манипулировать или отключать. Вот отличное представление о том, каково это – доверять любому виду проверки на стороне клиента.

Если мы продолжим с приведенным выше изображением, мы должны создать механизм проверки, который отклоняет любой другой номер, кроме 911, в качестве входного. Вот тут-то и вступает в игру проверка на стороне сервера. Вкратце, проверка на стороне сервера – это наш последний шанс правильно отклонить неверные входные данные. Кроме того, мы проверяем ограничения, которые требуют большего количества логических операций на стороне сервера. Например, отклонить создание сотрудника, если руководитель отдела еще не назначен. Достаточно для знакомства, давайте испачкаем руки.

Ограничения проверки Javax

javax.validation – это пакет верхнего уровня для API проверки компонентов, и в нем есть некоторые предопределенные ограничения на основе аннотаций в пакете ограничения , которые мы можем использовать. Вот несколько примеров.

  • Если мы хотим проверить поле, если оно равно нулю, мы используем @NotNull .
  @NotNull(message = "Name cannot be null.")
  private String name;

В приведенном выше примере имя поле не может быть пустым. Но он может быть пустым. Если мы используем @NotBlank имя не может быть нулевым и должно содержать по крайней мере один символ без пробела, или если мы используем @@Непустой аннотация имя не может быть нулевой и имя.длина() > 0 . Таким образом, он может принимать строку, содержащую пробельный символ.

-Если мы ограничиваем ввод любого числа, которое мы используем @Макс и @Мин аннотации.

  @Min(value = 3, message = "Experience must be at least 3 years.")
  private Integer experienceInYears;

@Положительный , @Отрицательный , @Положительный или нулевой и @Отрицательный или нулевой аннотации делают то, что предполагает их название.

  @PositiveOrZero(message = "You cannot have negative numbers of children.")
  private Integer numberOfChildren;

@Размер аннотация дает минимальные и максимальные значения для размера чего-либо. ( Последовательность символов , Коллекция , Карта , Массив )

  @Size(min = 2, max = 35, message = "Surname must be 2-35 characters long.")
  private String surname;

@Прошлое , @ @Будущее , @Прошлое присутствует , @FutureOrPresent

  @Past(message = "Date input is invalid for a birth date.")
  private LocalDate dateOfBirth;

-Вы можете проверить любой шаблон регулярного выражения с помощью аннотации @Pattern .

  @Pattern(regexp = "^4[0-9]{12}(?:[0-9]{3})?$", message = "Only Visa cards are accepted.")
  private String cardNumber;

-Не нужно объяснять @Mail аннотацию.

  @Email(message = "Enter a valid email address.")
  private String email;

Я объяснил наиболее важные из них выше. Если вы хотите увидеть остальных, вы можете найти их здесь.

Я создал фиктивный пример, чтобы попробовать эти ограничения и показывать сообщения о проверке при вводе формы с помощью Thymeleaf. Мы должны аннотировать ввод контроллера с помощью @Valid , чтобы активировать эти ограничения.

@PostMapping("/javax-constraints")
    String postJavaxConstraints(@Valid JavaxValidationConstraints javaxValidationConstraints, BindingResult bindingResult) {
        ...
        ...
        ...
    }

Затем отобразите сообщения об ошибках на Thymeleaf.

Создание Собственных Аннотаций Для Проверки

Если вы хорошо следили за предыдущей главой, вы должны были видеть, что вы достигаете почти всего с помощью ограничений проверки Javax. Но иногда определение собственных аннотаций может показаться гораздо лучшим вариантом.

Вот один пример. Мы хотим подтвердить кредитную карту поле с @шаблоном .

@NotEmpty(message = "You must enter a credit card number.")
@Pattern(regexp = "^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7]" 
                + "[0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}" 
                + "|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])" 
                + "[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$",
            message = "Invalid card number.")
private String creditCard;

Вы видите здесь какую-то проблему? Это кажется слишком уродливым, учитывая, что у нас будет еще как минимум 5 полей с как минимум 2 аннотациями проверки и так далее. В такой ситуации мы можем выбрать определение нашей собственной аннотации.

Прежде всего создайте аннотацию, как показано ниже.

@Documented
@Constraint(validatedBy = CreditCardValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CreditCard { 

    String message() default "Invalid card number";
    Class[] groups() default {};
    Class[] payload() default {};
 }

Мы хотим, чтобы наша аннотация работала во время выполнения, использовалась с типами полей и проверялась классом CreditCardValidator.

Итак, вот наш класс валидаторов.

public class CreditCardValidator implements ConstraintValidator {

    private static final String CREDIT_CARD_REGEX = "^(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$";

    private static final Pattern CREDIT_CARD_PATTERN = Pattern.compile(CREDIT_CARD_REGEX);

    @Override
    public void initialize(CreditCard constraintAnnotation) {

    }

    @Override
    public boolean isValid(String creditCardNumber, ConstraintValidatorContext context) {

        Matcher matcher = CREDIT_CARD_PATTERN.matcher(creditCardNumber);

        return matcher.matches();

    }
}

Мы реализуем ConstraintValidator<[Имя аннотации], [Тип цели]> и принудительно переопределяем инициализацию() и Методы isValid() . инициализировать метод гарантированно будет запущен перед любым использованием этой проверки, и isValid метод – это то, где мы отклоняем или принимаем любое значение.

Наша аннотация готова. Давайте использовать их так, как описано выше.

@PostMapping("/custom-constraint-annotation")
    String postCustomConstraint(@Valid CustomConstraintAnnotation customConstraintAnnotation, BindingResult bindingResult) {

        if(bindingResult.hasErrors()){

            return "custom-constraint-annotation";
        }
        ...
        ...
        ...
    }
}

Все ошибки проверки сохраняются в объекте BindingResult, и мы можем отображать сообщения об ошибках с помощью Thymeleaf.

Errors



Объединение Нескольких Аннотаций

Другим способом реализации хороших проверок является объединение нескольких аннотаций проверки. Документация по гибернации называет это Композиция ограничений . Это довольно просто. Прежде всего создайте тип аннотации и заполните, как показано ниже.

@NotEmpty
@Size(min = 8)
@Pattern(regexp = "\"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]$\"")
@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface CombinedPasswordConstraint {

    String message() default "Invalid password.";

    Class[] groups() default {};

    Class[] payload() default {};
}

Вы можете добавлять разные сообщения для каждой аннотации. Затем используйте его, как и другие ограничения.

Создание Пользовательского Класса Валидатора

До сих пор мы проходили через трудности. Пришло время создать более сложную проверку с помощью пользовательского класса валидатора. В предыдущих примерах мы проверяли синтаксические вещи. Но, как правило, нам нужны более сложные вещи, которые, возможно, требуют запроса к базе данных.

Я повторяю предыдущий пример. Вы создали отдел в своем воображаемом приложении. Когда вы пытаетесь добавить нового сотрудника в этот отдел. Но вы хотите добавить ограничение, которое требует назначения менеджера перед назначением сотрудника. Поэтому вам следует добавить валидатор, который проверяет, есть ли в этом отделе менеджер или нет. Это возможно с помощью пользовательского валидатора. Но вы также можете проверять простые вещи, такие как шаблоны регулярных выражений.

Давайте создадим его.

Я собираюсь показать вам упрощенный пример. Прежде всего, создайте фиктивный класс и заполните его, как показано ниже.

public class CustomValidationEntity {

    private String email;

    private Long departmentId;

    public Boolean existManagerByDepartmentId(Long departmentId) {

        return false;
    }

    public Boolean existEmployeeWithMail(String email) {

        return true;
    }

}

В нем всегда будет написано “в отделе нет менеджера” и “это электронное письмо уже существует”, что бы мы ни вводили.

Затем создайте класс валидатора, как показано ниже. Я собираюсь объяснить детали.

@Component
public class CustomValidator implements Validator {

    @Override
    public boolean supports(Class clazz) {
        return CustomValidationEntity.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {

        CustomValidationEntity customValidationEntity = (CustomValidationEntity) target;

        if (customValidationEntity.existEmployeeWithMail(customValidationEntity.getEmail())) {

            errors.rejectValue("email", null, "Employee with this email is already exists.");
        }

        if (!customValidationEntity.existManagerByDepartmentId(customValidationEntity.getDepartmentId())) {

            errors.reject(null, "Department does not have a manager.");
        }

    }
}

Этот интерфейс валидатора, который мы расширяем, называется org.springframework.validation. Валидатор; . Не явакс… один. Этот интерфейс предоставляет нам два метода. поддерживает() метод определяет, является ли целевой объект тем, что мы намеревались проверить, и validate() метод – это то, где мы контролируем и отклоняем вещи. Вы можете отклонить весь объект и добавить глобальное сообщение об ошибке с помощью reject() или отклонить одно значение и добавить сообщение об ошибке для этого значения с помощью rejectValue() . Затем вы должны аннотировать этот класс с помощью @Component .

Давайте воспользуемся нашим валидатором. Но мы сделаем что-то другое, чем использование ограничений. После аннотирования параметра объекта в контроллере с помощью @Valid мы добавим метод InitBinder в этот контроллер.

@InitBinder
private void bindValidator(WebDataBinder webDataBinder) {
    webDataBinder.addValidators(customValidator);
}

Этот @InitBinder аннотированный метод инициализирует WebDataBinder . Поскольку WebDataBinder подготавливает объекты, поступающие из запросов для контроллеров, он может выполнить проверку до того, как запрос достигнет контроллера. Это оно. Давайте попробуем на нашем примере.

В этой статье мы рассмотрели проверки в приложении Spring.

По вопросам, предложениям или исправлениям, не стесняйтесь обращаться ко мне по:

Электронная почта: kamer@kamerelciyar.com

Твиттер: Твиттер:

Оригинал: “https://dev.to/kamer/validations-in-spring-boot-6pk”