<mystore:formatValidator
formatPatterns="9999999999999999|9999 9999 9999 9999|9999-9999-9999-9999"/>
Java Platform, Enterprise Edition (Java EE) 8 Учебник по Java EE |
Назад | Вперёд | Содержание |
Если стандартные валидаторы или Bean Validation не выполняют необходимую вам проверки, вы можете создать кастомный валидатор для валидации пользовательского ввода. Как объясняется в Модель валидации, существует два способа реализации кода валидации.
Реализуйте метод Managed-бина, который выполняет валидацию.
Предоставьте реализацию интерфейса javax.faces.validator.Validator
для выполнения проверки.
Пишем метод для выполнения валидации объясняет, как реализовать метод Managed-бина для выполнения валидации. В оставшейся части этого раздела объясняется, как реализовать интерфейс Validator
.
Если вы решили реализовать интерфейс Validator
и хотите, чтобы автор страницы настраивал атрибуты валидатора со страницы, вы также должны указать кастомный тег для регистрации валидатора в компоненте.
Если вы предпочитаете настраивать атрибуты в реализации Validator
, вы можете отказаться от указания кастомного тега и вместо этого позволить автору страницы зарегистрировать валидатор в компоненте с помощью тега f:validator
, как описано в Использование кастомного валидатора.
Вы также можете создать свойство Managed-бина, которое принимает и возвращает созданную реализацию Validator
, как описано в Запись свойств, привязанных к конвертерам, слушателям или валидаторам. Вы можете использовать атрибут привязки тега f:validator
, чтобы связать реализацию Validator
со свойством Managed-бина.
Как правило, если данные не проходят валидацию, пользователю на странице отображаются соответствующие сообщения об ошибках. Необходимо хранить эти сообщения об ошибках в bundle-ресурсе.
После создания bundle-ресурса у вас есть два способа сделать сообщения доступными для приложения. Вы можете поместить сообщения об ошибках в FacesContext
программно или зарегистрировать сообщения об ошибках в файле конфигурации приложения, как описано в Регистрация сообщений приложения.
Например, приложение электронной торговли может использовать кастомный валидатор общего назначения с именем FormatValidator.java
для валидации введённых данных по шаблону формата, указанному в кастомном теге валидатора. Этот валидатор будет использоваться с полем Номер кредитной карты на странице Facelets. Вот кастомный тег валидатора:
<mystore:formatValidator
formatPatterns="9999999999999999|9999 9999 9999 9999|9999-9999-9999-9999"/>
Согласно этому валидатору, данные, введённые в поле, должны быть одним из следующих:
16-значный номер без пробелов
16-значный номер с пробелами между каждыми четырьмя цифрами
16-значный номер с дефисами между каждыми четырьмя цифрами
Тег f:validateRegex
делает ненужным кастомный валидатор в этой ситуации. Однако в оставшейся части этого раздела описывается, как этот валидатор будет реализован и как указать кастомный тег, чтобы автор страницы мог зарегистрировать валидатор в компоненте.
Реализация Validator
должна содержать конструктор, набор методов доступа для любых атрибутов тега и метод validate
, который переопределяет метод validate
интерфейса Validator
.
Гипотетический класс FormatValidator
также определяет методы доступа для установки атрибута formatPatterns
, который указывает приемлемые шаблоны формата для ввода в поля. Set-метод вызывает метод parseFormatPatterns
, который разделяет компоненты строки шаблона в строковый массив formatPatternsList
.
public String getFormatPatterns() {
return (this.formatPatterns);
}
public void setFormatPatterns(String formatPatterns) {
this.formatPatterns = formatPatterns;
parseFormatPatterns();
}
В дополнение к определению методов доступа для атрибутов, класс переопределяет метод validate
интерфейса Validator
. Этот метод проверяет ввод и также получает доступ к кастомным сообщениям об ошибках, которые отображаются, когда String
невалидный.
Метод validate
выполняет фактическую валидацию данных. Он принимает объект FacesContext
, компонент, данные которого необходимо проверить, и значение, которое необходимо проверить. Валидатор имеет возможность проверять только данные компонента, который реализует javax.faces.component.EditableValueHolder
.
Вот реализация метода validate
:
@FacesValidator
public class FormatValidator implements Validator, StateHolder {
...
public void validate(FacesContext context, UIComponent component,
Object toValidate) {
boolean valid = false;
String value = null;
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (!(component instanceof UIInput)) {
return;
}
if ( null == formatPatternsList || null == toValidate) {
return;
}
value = toValidate.toString();
// валидация значения по списку шаблонов.
Iterator patternIt = formatPatternsList.iterator();
while (patternIt.hasNext()) {
valid = isFormatValid(
((String)patternIt.next()), value);
if (valid) {
break;
}
}
if ( !valid ) {
FacesMessage errMsg =
new FacesMessage(FORMAT_INVALID_MESSAGE_ID);
FacesContext.getCurrentInstance().addMessage(null, errMsg);
throw new ValidatorException(errMsg);
}
}
}
Аннотация @FacesValidator
регистрирует класс FormatValidator
как валидатор с JavaServer Faces. Метод validate
получает локальное значение компонента и преобразует его в String
. Затем он перебирает список formatPatternsList
, являющийся списком допустимых шаблонов, которые были проанализированы из атрибута formatPatterns
кастомного тега валидатора.
Во время итерации по списку этот метод проверяет локальное значение компонента на соответствие шаблонам в списке. Если локальное значение не соответствует ни одному шаблону в списке, этот метод генерирует сообщение об ошибке. Затем он создаёт javax.faces.application.FacesMessage
и помещает его в очередь на FacesContext
для отображения, используя String
, который представляет ключ в файле Properties
:
public static final String FORMAT_INVALID_MESSAGE_ID =
"FormatInvalid";
}
Наконец, метод передаёт сообщение в конструктор javax.faces.validator.ValidatorException
.
Когда отображается сообщение об ошибке, {0}
будет заменён на шаблон формата в сообщении об ошибке, которое выглядит следующим образом:
Входные данные должны соответствовать одному из следующих шаблонов: {0}
Вы можете сохранить и восстановить состояние вашего валидатора, хотя сохранение состояния обычно не требуется. Для этого необходимо реализовать интерфейс StateHolder
, а также интерфейс Validator
. Чтобы реализовать StateHolder
, вам нужно реализовать четыре метода: saveState(FacesContext)
, restoreState(FacesContext, Object)
, isTransient
и setTransient(boolean)
. Смотрите Сохранение и восстановление состояния для получения дополнительной информации.
Если вы реализовали интерфейс Validator
, а не метод Managed-бина, который выполняет валидацию, вам нужно выполнить одно из следующих действий.
Разрешите автору страницы указывать реализацию Validator
для использования с тегом f:validator
. В этом случае реализация Validator
должна определять свои собственные свойства. Использование кастомного валидатора объясняет, как использовать тег f:validator
.
Укажите кастомный тег, который предоставляет атрибуты для настройки свойств валидатора со страницы.
Чтобы создать кастомный тег, необходимо добавить тег в дескриптор библиотеки тегов приложения, bookstore.taglib.xml
:
<tag>
<tag-name>validator</tag-name>
<validator>
<validator-id>formatValidator</validator-id>
<validator-class>
dukesbookstore.validators.FormatValidator
</validator-class>
</validator>
</tag>
Элемент tag-name
определяет имя тега, так как он должен использоваться на странице Facelets. Элемент validator-id
идентифицирует кастомный валидатор. Элемент validator-class
связывает кастомный тег с его классом реализации.
Использование кастомного валидатора объясняет, как использовать кастомный тег валидатора на странице.
Чтобы зарегистрировать кастомный валидатор в компоненте, необходимо выполнить одно из следующих действий.
Вложите кастомный тег валидатора в тег компонента, значение которого вы хотите проверить.
Вложите стандартный тег f:validator
в тег компонента и укажите ссылку на реализацию кастомного Validator
из тега f:validator
.
Вот гипотетический кастомный тег formatValidator
для поля Credit Card Number, вложенный в тег h:inputText
:
<h:inputText id="ccno" size="19"
...
required="true">
<mystore:formatValidator
formatPatterns="9999999999999999|9999 9999 9999 9999|9999-9999-9999-9999"/>
</h:inputText>
<h:message styleClass="validationMessage" for="ccno"/>
Этот тег проверяет ввод поля ccno
по шаблонам, определённым автором страницы в атрибуте formatPatterns
.
Вы можете использовать один и тот же кастомный валидатор для любого аналогичного компонента, просто вложив кастомный тег валидатора в тег компонента.
Если разработчик приложения, создавший кастомный валидатор, предпочитает настраивать атрибуты в реализации Validator
, а не разрешать автору страницы настраивать атрибуты со страницы, разработчик не будет создавать кастомный тег для использования с валидатором.
В этом случае автор страницы должен вложить тег f:validator
в тег компонента, данные которого необходимо валидировать. Затем автору страницы необходимо выполнить одно из следующих действий.
Задайте для атрибута validatorId
тега f:validator
идентификатор валидатора, определённый в файле конфигурации приложения.
Свяжите реализацию кастомного Validator
со свойством Managed-бина, используя атрибут binding
тега f:validator
, как описано в Связывание конвертеров, слушателей и валидаторов со свойствами Managed-бина.
Следующий тег регистрирует гипотетический валидатор в компоненте с помощью тега f:validator
и ссылается на идентификатор валидатора:
<h:inputText id="name" value="#{CustomerBean.name}"
size="10" ...>
<f:validator validatorId="customValidator" />
...
</h:inputText>
Назад | Вперёд | Содержание |