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 extends Payload>[] 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-формы:
Чтобы завершить все это, мы можем запустить ваше приложение как приложение Spring Boot:
@SpringBootApplication public class DynamicValidationApp { public static void main(String[] args) { SpringApplication.run(DynamicValidationApp.class, args); } }
5. Заключение
В этом примере мы показали, как можно создать пользовательскую аннотацию проверки, которая динамически извлекает регулярное выражение из базы данных и использует его для проверки аннотированного поля.
Полный исходный код примера можно найти на GitHub .