Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Пишем методы Managed-бинов

Методы Managed-бина могут выполнять несколько специфичных для приложения функций. Эти функции включают

  • Выполнение обработки, связанной с навигацией

  • Обработка событий действия

  • Выполнение валидации значения компонента

  • Обработка событий изменения значения

Зачем использовать Managed-бины

Используя Managed-бин для выполнения этих функций, вы устраняете необходимость реализации интерфейса javax.faces.validator.Validator для обработки валидации или одного из интерфейсов слушателя для обработки событий. Кроме того, используя Managed-бин вместо реализации Validator для выполнения валидации, вы устраняете необходимость создания кастомного тега для реализации Validator.

Как правило, рекомендуется включать эти методы в один и тот же Managed-бин, определяющий свойства компонентов, ссылающихся на эти методы. Причина заключается в том, что методам может потребоваться доступ к данным компонента, чтобы определить, как обрабатывать событие, или выполнить валидацию, связанную с компонентом.

В следующих разделах объясняется, как писать различные типы методов Managed-бина.

Пишем метод для обработки навигации

Метод действия — метод Managed-бина, который обрабатывает навигацию — должен быть публичным методом, который не принимает параметров и возвращает Object, являющийся сигналом навигационной системе для определения следующей отображаемой страницы. На этот метод ссылается атрибут action тега компонента.

Следующий метод действия взят из Managed-бина CashierBean, который вызывается, когда пользователь кликает кнопку «Отправить» на странице. Если пользователь заказал книги стоимостью более 100 долларов, этот метод устанавливает свойства rendered компонентов fanClub и specialOffer в true, заставляя их отображаться на странице при следующем отображении страницы.

После установки свойств rendered компонентов в true этот метод возвращает результат null. Это приводит к тому, что JavaServer Faces повторно отображает страницу без создания нового представления, сохраняя введённые пользователем данные. Если бы этот метод возвратил purchase, что является сигналом для перехода на страницу оплаты, страница была бы повторно отображена без сохранения ввода клиента. В этом случае вы перерисовываете страницу без очистки данных.

Если пользователь не покупает книг на сумму более 100 долларов США или компонент thankYou уже отрисован, метод возвращает bookreceipt. JavaServer Faces загружает страницу bookreceipt.xhtml после возврата из этого метода:

public String submit() {
    ...
    if ((cart().getTotal()> 100.00) && !specialOffer.isRendered()) {
        specialOfferText.setRendered(true);
        specialOffer.setRendered(true);
        return null;
    } else if (specialOffer.isRendered() && !thankYou.isRendered()) {
        thankYou.setRendered(true);
        return null;
    } else {
        ...
        cart.clear();
        return ("bookreceipt");
    }
}

Как правило, метод действия возвращает результат String, как показано в предыдущем примере. Кроме того, вы можете определить класс Enum, который инкапсулирует все возможные строки результата, а затем заставить метод действия возвращать константу enum, которая представляет конкретный результат String, определяемый классом Enum.

В следующем примере используется класс Enum для инкапсуляции всех результатов:

public enum Navigation  {
    main, accountHist, accountList, atm, atmAck, transferFunds,
     transferAck, error
}

Когда он возвращает результат, метод действия использует точечную нотацию для ссылки на результат из класса Enum:

public Object submit(){
    ...
    return Navigation.accountHist;
}

В разделе Ссылка на метод, который выполняет навигацию объясняется, как тег компонента ссылается на этот метод. В разделе Запись свойств, связанных с объектами компонентов объясняется, как записать свойства бинов, с которыми связаны компоненты.

Пишем метод-обработчик действия

Метод Managed-бина, который обрабатывает событие действия, должен быть публичным методом, который принимает событие действия и возвращает void. На этот метод ссылается атрибут actionListener тега компонента. Только компоненты, которые реализуют javax.faces.component.ActionSource, могут ссылаться на этот метод.

В следующем примере метод из Managed-бина с именем ActionBean обрабатывает событие, когда пользователь кликает одну из ссылок на странице:

public void chooseBookFromLink(ActionEvent event) {
    String current = event.getComponent().getId();
    FacesContext context = FacesContext.getCurrentInstance();
    String bookId = books.get(current);
    context.getExternalContext().getSessionMap().put("bookId", bookId);
}

Этот метод получает из объекта события компонент, который сгенерировал это событие. Затем он получает идентификатор компонента, который является кодом книги. Метод сопоставляет код с объектом HashMap, который содержит коды книг и соответствующие значения идентификаторов книг. Наконец, метод устанавливает идентификатор книги, используя выбранное значение из объекта HashMap.

Ссылка на метод-обработчик действия объясняет, как тег компонента ссылается на этот метод.

Пишем метод для выполнения валидации

Вместо реализации интерфейса javax.faces.validator.Validator для выполнения валидации компонентом, вы можете включить метод в Managed-бин и таким образом позаботиться о валидации входных данных компонента. Метод Managed-бина, который выполняет валидацию, должен принимать javax.faces.context.FacesContext, компонент, данные которого должны быть проверены, и данные, подлежащие проверке, так же, как метод validate интерфейса Validator. Компонент ссылается на метод Managed-бина с использованием его атрибута validator. Провалидированы могут быть только значения компонентов UIInput или его дочерних.

Вот пример метода Managed-бина, который проверяет пользовательский ввод, из примера CDI guessnumber-cdi:

public void validateNumberRange(FacesContext context,
                                UIComponent toValidate,
                                Object value) {
    if (remainingGuesses <= 0) {
        ((UIInput) toValidate).setValid(false);
        FacesMessage message = new FacesMessage("No guesses left!");
        context.addMessage(toValidate.getClientId(context), message);
        return;
    }

    int input = (Integer) value;
    if (input < minimum || input> maximum) {
        ((UIInput) toValidate).setValid(false);

        FacesMessage message = new FacesMessage("Invalid guess");
        context.addMessage(toValidate.getClientId(context), message);
    }
}

Метод validateNumberRange выполняет две разные валидации.

  • Если у пользователя закончились предположения, метод устанавливает свойству valid компонента UIInput значение false. Затем он помещает сообщение в очередь на объект FacesContext, связывая сообщение с идентификатором компонента, и возвращает результат.

  • Если у пользователя ещё остались предположения, метод получает локальное значение компонента. Если входное значение находится за пределами допустимого диапазона, метод снова устанавливает свойство valid компонента UIInput в false, помещая другое сообщение в очередь объекта FacesContext и возвращает результат.

Смотрите Ссылка на метод, который выполняет валидацию для получения информации о том, как тег компонента ссылается на этот метод.

Пишем метод-обработчик изменения значения

Managed-бин, который обрабатывает событие изменения значения, должен использовать публичный метод, который принимает событие изменения значения и возвращает void. На этот метод ссылается атрибут valueChangeListener компонента. В этом разделе объясняется, как написать метод Managed-бина для замены реализации javax.faces.event.ValueChangeListener.

Следующий пример тега взят из Регистрация слушателя изменения значения в компоненте, где тег h:inputText с id из name имеет зарегистрированный объект ValueChangeListener. Этот объект ValueChangeListener обрабатывает событие ввода значения в поле, соответствующее компоненту. Когда пользователь вводит значение, генерируется событие изменения значения и вызывается метод processValueChange(ValueChangeEvent) класса ValueChangeListener:

<h:inputText id="name"
             size="30"
             value="#{cashierBean.name}"
             required="true"
             requiredMessage="#{bundle.ReqCustomerName}">
     <f:valueChangeListener
         type="javaeetutorial.dukesbookstore.listeners.NameChanged" />
</h:inputText>

Вместо реализации ValueChangeListener вы можете написать метод Managed-бина для обработки этого события. Для этого вы перемещаете метод processValueChange(ValueChangeEvent) из класса ValueChangeListener, называемого NameChanged, в Managed-бин.

Вот метод Managed-бина, который обрабатывает событие ввода значения в поле name на странице:

public void processValueChange(ValueChangeEvent event)
        throws AbortProcessingException {
    if (null != event.getNewValue()) {
        FacesContext.getCurrentInstance().getExternalContext().
                getSessionMap().put("name", event.getNewValue());
    }
}

Чтобы этот метод обрабатывал ValueChangeEvent, сгенерированный компонентом ввода, обратитесь к этому методу из атрибута valueChangeListener тега компонента. Смотрите Ссылка на метод-обработчик изменения значения для получения дополнительной информации.


Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)