1. Обзор
В этом руководстве мы рассмотрим ограничения Hibernate Validator, которые встроены в Hibernate Validator, но не входят в спецификацию Bean Validation.
Краткий обзор проверки бинов можно найти в нашей статье Основы валидации бинов Java .
2. Настройка гибернационного валидатора
По крайней мере, мы должны добавить Hibernate Validator к нашим зависимостям:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
Обратите внимание, что Hibernate Validator не зависит от Hibernate, ORM, о котором мы говорили во многих других статьях.
Кроме того, некоторые аннотации, которые мы представим, применимы только в том случае, если в нашем проекте используются определенные библиотеки. Итак, для каждого из них мы укажем необходимые зависимости.
3. Проверка денежных ценностей
3.1. Проверка номеров кредитных карт
Действительные номера кредитных карт должны удовлетворять контрольной сумме, которую мы вычисляем с помощью алгоритма Луна . Ограничение @CreditCardNumber выполняется
успешно, когда строка удовлетворяет контрольной сумме.
@CreditCardNumber
не выполняет никакой другой проверки входной строки. В частности, он не проверяет длину ввода. Поэтому он может обнаруживать только числа, которые недействительны из-за небольшой опечатки.
Обратите внимание, что по умолчанию ограничение не работает, если строка содержит символы, не являющиеся цифрами, но мы можем указать, чтобы она их игнорировала:
@CreditCardNumber(ignoreNonDigitCharacters = true)
private String lenientCreditCardNumber;
Затем мы можем включить символы, такие как пробелы или тире:
validations.setLenientCreditCardNumber("7992-7398-713");
constraintViolations = validator.validateProperty(validations, "lenientCreditCardNumber");
assertTrue(constraintViolations.isEmpty());
3.2. Проверка денежных значений
Валидатор @Currency
проверяет, находится ли данная денежная сумма в указанной валюте:
@Currency("EUR")
private MonetaryAmount balance;
Класс MonetaryAmount
является частью Java Money. Поэтому @Currency
применяется только тогда, когда доступна реализация Java Money .
Как только мы правильно настроим Java Money, мы можем проверить ограничение:
bean.setBalance(Money.of(new BigDecimal(100.0), Monetary.getCurrency("EUR")));
constraintViolations = validator.validateProperty(bean, "balance");
assertEquals(0, constraintViolations.size());
4. Проверка диапазонов
4.1. Числовые и денежные диапазоны
Спецификация проверки бина определяет несколько ограничений, которые мы можем применить к числовым полям. Помимо этого, Hibernate Validator предоставляет удобную аннотацию @Range
, которая действует как комбинация @Min
и @Max,
включая диапазон:
@Range(min = 0, max = 100)
private BigDecimal percent;
Подобно @Min
и @Max
, @Range
применим к полям примитивных числовых типов и их оболочкам; BigInteger
и BigDecimal
, строковые
представления вышеперечисленного и, наконец, поля MonetaryValue .
4.2. Продолжительность времени
В дополнение к стандартным аннотациям JSR 380 для значений, представляющих моменты времени, Hibernate Validator также включает ограничения для Duration
s. Обязательно сначала ознакомьтесь с классами Period
и Duration
Java Time .
Итак, мы можем установить минимальную и максимальную продолжительность для свойства:
@DurationMin(days = 1, hours = 2)
@DurationMax(days = 2, hours = 1)
private Duration duration;
Даже если мы не показали их все здесь, в аннотации есть параметры для всех единиц времени от наносекунд до суток.
Обратите внимание, что по умолчанию минимальные и максимальные значения включаются. То есть значение, которое точно совпадает с минимальным или максимальным значением, пройдет проверку.
Если мы хотим, чтобы граничные значения были недействительными, вместо этого мы определяем включающее
свойство как ложное:
@DurationMax(minutes = 30, inclusive = false)
5. Проверка строк
5.1. Длина строки
Мы можем использовать два немного разных ограничения, чтобы обеспечить заданную длину строки.
Как правило, мы хотим убедиться, что длина строки в символах — та, которую мы измеряем с помощью метода длины
, — находится между минимумом и максимумом. В этом случае мы используем @Length
для свойства или поля String:
@Length(min = 1, max = 3)
private String someString;
Однако из-за сложности Unicode иногда длина в символах и длина в кодовых точках различаются. Когда мы хотим проверить последнее, мы используем @CodePointLength:
@CodePointLength(min = 1, max = 3)
private String someString;
Например, строка «aa\uD835\uDD0A» имеет длину 4 символа, но содержит только 3 кодовых точки, поэтому первое ограничение не будет выполнено, а второе пройдет.
Кроме того, с обеими аннотациями мы можем опустить минимальное или максимальное значение.
5.2. Проверка строк цифр
Мы уже видели, как проверить, что строка является допустимым номером кредитной карты. Однако Hibernate Validator включает несколько других ограничений для строк цифр.
Первым, кого мы рассматриваем, является @LuhnCheck.
Это обобщенная версия @CreditCardNumber,
поскольку она выполняет ту же проверку, но допускает дополнительные параметры:
@LuhnCheck(startIndex = 0, endIndex = Integer.MAX_VALUE, checkDigitIndex = -1)
private String someString;
Здесь мы показали значения параметров по умолчанию, поэтому приведенное выше эквивалентно простой аннотации @LuhnCheck
.
Но, как мы видим, мы можем выполнить проверку подстроки ( startIndex
и endIndex
) и сообщить ограничению, какая цифра является цифрой контрольной суммы, где -1 означает последнюю в проверяемой подстроке.
Другие интересные ограничения включают проверку по модулю 10 ( @Mod10Check
) и проверку по модулю 11 ( @Mod11Check
), которые обычно используются для штрих-кодов и других кодов, таких как ISBN.
Однако для этих конкретных случаев Hibernate Validator предоставляет ограничение для проверки кодов ISBN, @ISBN
, а также ограничение @EAN
для штрих- кодов EAN .
5.3. Проверка URL и HTML
Ограничение @Url
проверяет, является ли строка допустимым представлением URL-адреса. Кроме того, мы можем проверить, что конкретный компонент URL-адреса имеет определенное значение:
@URL(protocol = "https")
private String url;
Таким образом, мы можем проверить протокол, хост и порт. Если этого недостаточно, есть свойство регулярного выражения
, которое мы можем использовать для сопоставления URL-адреса с регулярным выражением.
Мы также можем проверить, что свойство содержит «безопасный» HTML-код (например, без тегов скрипта):
@SafeHtml
private String html;
@SafeHtml
использует библиотеку JSoup , которую необходимо включить в наши зависимости.
Мы можем настроить очистку HTML в соответствии с нашими потребностями, используя встроенные белые списки тегов ( свойство whitelist аннотации) и включая
дополнительные
теги и атрибуты (параметры AdditionalTags и AdditionalTagsWithAttributes
).
6. Другие ограничения
Кратко упомянем, что Hibernate Validator включает в себя некоторые ограничения, зависящие от страны и региона, в частности, для некоторых бразильских и польских идентификационных номеров, кодов налогоплательщиков и тому подобного. Пожалуйста, обратитесь к соответствующему разделу документации для получения полного списка.
Кроме того, мы можем проверить, что коллекция не содержит дубликатов с помощью @UniqueElements.
Наконец, для сложных случаев, не охватываемых существующими аннотациями, мы можем вызвать сценарий, написанный в совместимом с JSR-223 механизме сценариев. Мы, конечно же, коснулись JSR-223 в нашей статье о Nashorn , реализации JavaScript, включенной в современные JVM.
В этом случае аннотация находится на уровне класса, а скрипт вызывается для всего экземпляра, передаваемого как переменная _this:
@ScriptAssert(lang = "nashorn", script = "_this.valid")
public class AdditionalValidations {
private boolean valid = true;
// standard getters and setters
}
Затем мы можем проверить ограничение на весь экземпляр:
bean.setValid(false);
constraintViolations = validator.validate(bean);
assertEquals(1, constraintViolations.size());
7. Заключение
В этой статье мы перечислили ограничения в Hibernate Validator, которые выходят за рамки минимального набора, определенного в спецификации Bean Validation.
Реализацию всех этих примеров и фрагментов кода можно найти на GitHub .