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

Конфигурация динамической проверки DTO, полученная из базы данных

Краткое практическое руководство по созданию пользовательской динамической аннотации проверки DTO, которая извлекает свои конфигурации из базы данных.

Автор оригинала: baeldung.

1. Обзор

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

Мы будем использовать валидатор Hibernate в качестве базовой реализации.

2. Зависимости Maven

Для разработки нам понадобятся следующие зависимости:


    org.springframework.boot
    spring-boot-starter-thymeleaf
    2.4.0


    org.springframework.boot
    spring-boot-starter-data-jpa
    2.4.0

Последние версии spring-boot-starter-thymeleaf , spring-boot-starter-data-jpa можно загрузить с Maven Central.

3. Пользовательская проверка аннотации

В нашем примере мы создадим пользовательскую аннотацию с именем @ContactInfo , которая будет проверять значение на соответствие регулярному выражению, полученному из базы данных. Затем мы применим эту проверку в поле контактная информация класса POJO с именем Клиент .

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

3.1. Модели данных и Репозиторий

Давайте создадим класс Customer с полями id и контактная информация :

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String contactInfo;

    // standard constructor, getters, setters
}

Далее давайте рассмотрим класс ContactInfoExpression , который будет содержать значения регулярных выражений в свойстве с именем pattern :

@Entity
public class ContactInfoExpression {

    @Id
    @Column(name="expression_type")
    private String type;
 
    private String pattern;

    //standard constructor, getters, setters
}

Далее, давайте добавим интерфейс репозитория на основе данных Spring для управления выражением Контактная информация сущности:

public interface ContactInfoExpressionRepository 
  extends Repository {
 
    Optional findById(String id);
}

3.2. Настройка базы данных

Для хранения регулярных выражений мы будем использовать базу данных H2 в памяти со следующей конфигурацией сохранения:

@EnableJpaRepositories("com.baeldung.dynamicvalidation.dao")
@EntityScan("com.baeldung.dynamicvalidation.model")
@Configuration
public class PersistenceConfig {

    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2)
          .addScript("schema-expressions.sql")
          .addScript("data-expressions.sql")
          .build();
        return db;
    }
}

Два упомянутых скрипта используются для создания схемы и вставки данных в таблицу contact_info_expression :

CREATE TABLE contact_info_expression(
  expression_type varchar(50) not null,
  pattern varchar(500) not null,
  PRIMARY KEY ( expression_type )
);

Скрипт data-expressions.sql добавит три записи для представления типов электронная почта , телефон и веб-сайт . Они представляют собой регулярные выражения для проверки того, что значение является действительным адресом электронной почты, действительным номером телефона в США или действительным URL-адресом:

insert into contact_info_expression values ('email',
  '[a-z0-9!#$%&*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?')
insert into contact_info_expression values ('phone',
  '^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$')
insert into contact_info_expression values ('website',
  '^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$')

3.3. Создание пользовательского валидатора

Давайте создадим класс Contact Info Validator , который содержит фактическую логику проверки. Следуя рекомендациям спецификации проверки Java, класс реализует ConstraintValidator interface и переопределяет метод isValid () .

Этот класс получит значение используемого в данный момент типа контактной информации — электронная почта , телефон, или веб — сайт – которое задано в свойстве с именем contactInfoType , а затем использует его для извлечения значения регулярного выражения из базы данных:

public class ContactInfoValidator implements ConstraintValidator {
    
    private static final Logger LOG = Logger.getLogger(ContactInfoValidator.class);

    @Value("${contactInfoType}")
    private String expressionType;

    private String pattern;
 
    @Autowired
    private ContactInfoExpressionRepository expressionRepository;

    @Override
    public void initialize(ContactInfo contactInfo) {
        if (StringUtils.isEmptyOrWhitespace(expressionType)) {
            LOG.error("Contact info type missing!");
        } else {
            pattern = expressionRepository.findById(expressionType)
              .map(ContactInfoExpression::getPattern).get();
        }
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (!StringUtils.isEmptyOrWhitespace(pattern)) {
            return Pattern.matches(pattern, value);
        }
        LOG.error("Contact info pattern missing!");
        return false;
    }
}

Тип контактной информации свойство может быть установлено в файле application.properties в одно из значений электронная почта , телефон или веб-сайт :

contactInfoType=email

3.4. Создание аннотации пользовательского ограничения

А теперь давайте создадим интерфейс аннотаций для нашего пользовательского ограничения:

@Constraint(validatedBy = { ContactInfoValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactInfo {
    String message() default "Invalid value";

    Class[] groups() default {};

    Class[] payload() default {};
}

3.5. Применение пользовательского ограничения

Наконец, давайте добавим аннотации проверки в поле контактная информация нашего Клиента класса:

public class Customer {
    
    // ...
    @ContactInfo
    @NotNull
    private String contactInfo;
    
    // ...
}

4. Пружинный контроллер и HTML-форма

Чтобы проверить нашу аннотацию проверки, мы создадим сопоставление запросов Spring MVC, которое использует аннотацию @Valid для запуска проверки объекта Customer :

@PostMapping("/customer")
public String validateCustomer(@Valid Customer customer, BindingResult result, Model model) {
    if (result.hasErrors()) {
        model.addAttribute("message", "The information is invalid!");
    } else {
        model.addAttribute("message", "The information is valid!");
    }
    return "customer";
}

Объект Customer отправляется контроллеру из HTML-формы:

Contact Info:

Чтобы завершить все это, мы можем запустить ваше приложение как приложение Spring Boot:

@SpringBootApplication
public class DynamicValidationApp {
    public static void main(String[] args) {
        SpringApplication.run(DynamicValidationApp.class, args);
    }
}

5. Заключение

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

Полный исходный код примера можно найти на GitHub .