Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2013_1 / КСТ / Разработка веб-приложений.pdf
Скачиваний:
160
Добавлен:
23.02.2015
Размер:
2.74 Mб
Скачать

8. Внешние объекты (JavaBeans)

Типичное приложение JSF содержит один или более внешних объектов, ко-

торые управляют объектами, связываются с компонентами UI, использованными на конкретной странице. Внешние бины являются компонентами JavaBeans, которые вы

должны сконфигурировать. Есть особенности, определяемые ролью JavaBeans в ор-

ганизации и функционировании компонент JSF. Ниже приводятся основные сведения

о создании, конфигурации и использовании внешних бинов в приложении.

8.1. Создание класса внешних объектов

Внешние бины являются экземплярами классов с конструктором без параме-

тров, набором методов get/set для доступа к свойствам, используемым компонентами,

и методов, которые выполняют бизнес-логику для компонента.

Каждое свойство бина может быть связано:со значением атрибута компонента,

с экземпляром компонента,экземпляром конвертера,экземпляром слушателя,экземпляром для проверки значений.

Наиболее общие функции, которые выполняют методы внешних бинов, включают следующее:

подтверждение правильности данных от компонентов;обработка событий, созданных компонентом;

обработка данных для определения следующей страницы, на которую при-

ложение должно перейти (навигация).

Как у всех компонент JavaBeans, свойства состоят из полей приватных данных и набора методов set/get доступа к ним, как показано кодом из примера GuessNumber:

private Integer userNumber = null; // место хранения значения свойства

...

public void setUserNumber(Integer user_number) {

// метод set

userNumber = user_number;

 

}

 

public Integer getUserNumber() {

// метод get

return userNumber;

 

}

 

public String getResponse() {

// прочие методы

...

 

}

 

Поскольку все внешние бины следуют соглашениям JavaBeans, вы можете использовать объекты, ранее написанные для JSP-технологии.

Когда свойство бина связано со значением атрибута компонента, оно может

быть любым базовым примитивом, числовым типом или любым объектным типом

73

языка Java, для которого приложение имеет доступ к подходящему преобразова-

телю. Например, свойство может быть типа Date, если приложение имеет доступ к преобразователю типа Date в String и обратно. Необходимость использования пре-

образователей продиктована тем, что клиенту и от клиента данные посылаются как

строки — следствие использования протокола http для их передачи.

Когда свойство бина связано с экземпляром компонента, тип должен быть та-

ким же, как и тип компонента. Например, если свойство связано с SelectBoolean, то оно должно принимать и возвращать объект класса SelectBoolean.

Аналогично, если свойство связано с преобразователем, проверкой или экзем-

пляром слушателя, оно должно быть класса, подходящего для преобразователя, про-

верки значений или слушателя.

Использование унифицированного языка выражений EL для ссылок на внешние объекты

Для связывания значений компонентов и свойств внешних объектов или для ссылок на методы внешних объектов из тегов компонент авторы страниц используют

унифицированный язык выражения (EL). Он имеет следующие черты:отложенная оценка выражений;

способность использовать выражения-значения как для чтения, так и для записи данных;

использование выражений для подключения необходимых методов.

Отложенная оценка выражений необходима, поскольку жизненный цикл

JavaServer Faces разделен на отдельные фазы: обработка событий у компонент, преобразование данных и подтверждение правильности, передача данных во внешние бины. Сервер должен быть способен задержать оценку выражений, пока не наступила соответствующая фаза жизненного цикла. Следовательно, атрибут тега всегда исполь-

зует синтаксис задержанных вычислений, который задан разделителями «#{ . . . }».

Для того чтобы хранить данные во внешних объектах, почти все атрибуты тегов JSF используют выражения value, которые допускают как получение, так и запись данных во внешних объектах. Наконец, некоторые атрибуты компонентных тегов принимают имена методов, обрабатывающих компонентные события, контролирующих

или преобразовывающих компонентные данные.

Для иллюстрации тега, использующего унифицированный EL, будем полагать, что тег userNo приложения guessNumber ссылается на свой метод validate вместо использования LongRangeValidator, выполняющего стандартную проверку ввода поль-

зователя:

<h:inputText id="userNo" value="#{userNumberBean.userNumber}" validator="#{userNumberBean.validate}" />

Этот тег связывает компонент ввода userNo со свойством userNumber внешне-

го объекта userNumberBean, возвращающим данные с использованием выражения value. Оноиспользуетвыражение,чтобыссылатьсянаметодuserNumberBean.validate,

который выполняет контроль полученного значения. Локальное значение — любое данное, которое пользователь вводит в поле, соответствующее тегу. Этот метод про-

верки вызывается тогда, когда выражение оценивается в фазе контроля в жизненном

цикле запроса, поступившего от клиента.

74

Почти все атрибуты тегов допускают выражения. В дополнение к свойствам

объектов, значения выражения могут также ссылаться на списки, карты, массивы, встроенные объекты и пачки ресурсов.

Другое использование выражений связывает экземпляр компонента со свой-

ством внешнего объекта. Этот механизм позволяет в период исполнения приложения

программно изменять атрибуты тегов. Автор страницы делает это с помощью связы-

вающего атрибута binding со свойством, содержащим описание компонента:

<inputText binding="#{userNumberBean.userNoComponent}" />

Дополнительно к использованию выражений со стандартными компонентными

тегами, вы можете также конфигурировать ваши собственные свойства компонен-

тов, чтобы вычислять выражения, создавая для них экземпляры ValueExpression или

MethodExpression.

8.2. Описание свойств бинов

Как сказано выше, свойство внешнего бина может быть связанным с одним из

следующих пунктов:

значение данных компонента,

экземпляр компонента,

реализация преобразователя,

реализация слушателя,

реализация проверки (validator).

Эти свойства следуют соглашениям о компонентах JavaBeans (бины).

Тег компонента связывает его со свойством внешнего бина, используя атрибут value, или связывает экземпляр компонента со свойством внешнего бина, используя

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

Связываемые свойства и данные компонента должны иметь одинаковый тип. Например, если компонент имеет тип SelectBoolean, то и внешнее свойство должно возвращать данное типа SelectBoolean.

Описание связи свойства с атрибутами данных компонента

В табл. 8.1 содержатся компоненты и типы их данных.

 

Таблица 8.1

 

Компоненты и типы их значений

 

 

 

Компонент

Тип данных

 

Input, Output, SelectItem,

Любой основной примитив и числовые и другие типы языка

 

SelectOne

программирования Java, для которых доступна подходящая

 

 

реализация конвертера

 

Data

Массив бинов, список бинов, одиночный бин, java.sql.ResultSet,

 

 

javax.servlet.jsp.jstl.sql.Result, javax.sql.RowSet

 

SelectBoolean

boolean или Boolean

 

SelectItems

java.lang.String, Collection,Array, Map

 

SelectMany

Массив или список элементов любого стандартного типа

 

75

Свойства компонент Input и Output

В следующем примере тег h:inputText связывает значение компонента со свойством name внешнего бина с именем cashier в классе CashierBean:

<h:inputText id="name" size="50» value="#{cashier.name}" </h:inputText>

Следующий фрагмент кода CashierBean показывает тип свойства, связанного

с предыдущим компонентным тегом. Обратите внимание на правила написания имен методов и свойств: свойство и внутренняя переменная — name, методы — setName

и getName:

private String name = null;

public void setName(String name) { // Запись свойства this.name = name;

}

public String getName() {

// Чтение свойства

return this.name;

 

}

 

Чтобы преобразовывать значение компонентов Input или Output, вы можете использовать преобразователь или создать связь свойства бина с компонентом сопоставимого типа. Ниже приведен пример из описания DateTimeConverter, который отображает дату заказа книги:

<h:outputText value="#{cashier.shipDate}"> <f:convertDateTime dateStyle="full" />

</h:outputText>

Свойство,представленноеэтимтегом,должнобытьтипаjava.util.Date.Фрагмент описания класса CashierBean показывает объявление свойства shipDate, которое связано со значением тега в предыдущем примере:

private Date shipDate; public Date getShipDate() {

return this.shipDate;

}

public void setShipDate(Date shipDate) { this.shipDate = shipDate;

}

Свойства типа Data

Компоненты данных из таблиц БД должны иметь один из типов, указанных в табл. 8.1. Пример начальной части тега dataTable:

<h:dataTable id="items"

...

value="#{cart.items}" var="item" >

Значение выражения атрибута value указывает на свойство items бина с именем cart. Бин cart поддерживает отображение набора бинов класса ShoppingCartItem

в хранилище данных, например, средствами Persistence.

76

Метод getItems бина cart возвращает список экземпляров ShoppingCartItem, которые хранились в базе данных, когда клиент добавлял книги в корзину. Пример по-

казан в следующем коде:

public synchronized List getItems() {

// Создание копии

List results = new ArrayList();

results.addAll(this.items.values());

// Заполнение копии

return results;

// Копия как результат

}

 

Все компоненты, содержащиеся в компоненте Data, связаны со свойствами бина cart, который помещен в компонент Data. Например, тег h:outputText показывает

название книги в таблице:

<h:commandLink action="#{showcart.details}"> <h:outputText value="#{item.item.title}"/>

</h:commandLink>

Свойства SelectBoolean

Свойства бина, которые содержат данные SelectBoolean, должны быть типа boolean или Boolean. Пример тега selectBooleanCheckbox связывает компонент и

свойство логического типа:

<h:selectBooleanCheckbox title="#{bundle.receiveEmails}" value="#{custFormBean.receiveEmails}" >

</h:selectBooleanCheckbox>

<h:outputText value="#{bundle.receiveEmails}">

Пример свойства бина, которое может быть связано с тегом этого компонента:

protected boolean receiveEmails = false;

...

public void setReceiveEmails(boolean receiveEmails) { this.receiveEmails = receiveEmails;

}

public boolean getReceiveEmails() { return this.receiveEmails;

}

Свойство SelectMany

Поскольку компонент SelectMany позволяет пользователю выбирать один или

более пунктов из списка, этот компонент должен отображаться в свойство бина типа

List или array. Это свойство представляет набор выбранных в настоящее время пунктов из списка доступных. Пример тега SelectingMultiple:

<h:selectManyCheckbox

id="newsletters"

layout="pageDirection"

value="#{cashier.newsletters}">

<f:selectItems value="#{cashier.newsletters}"/> </h:selectManyCheckbox>

77

Пример свойства бина, которое отображается в значение тега selectManyCheckbox из предыдущего примера:

protected String newsletters[] = new String[0];

public void setNewsletters(String newsletters[]) { this.newsletters = newsletters;

}

public String[] getNewsletters() { return this.newsletters;

}

Компоненты SelectItem и SelectItems используются, чтобы задавать пункты в

компоненте SelectMany.

Свойства SelectOne

Свойства SelectOne принимают те же типы, как свойства Input и Output, посколь-

ку компонент SelectOne представляет единственный выбранный пункт из множества

пунктов. Этот пункт может быть любым простым типом или любым данным, для кото-

рого вы можете применить преобразователь.

Пример тега selectOneMenu:

<h:selectOneMenu id=”shippingOption” required=”true”

value=”#{cashier.shippingOption}”> // Куда принять результат <f:selectItem

itemValue=”2” // Вариант результата itemLabel=”#{bundle.QuickShip}”/> // Его представление

<f:selectItem

itemValue=”5”

itemLabel=”#{bundle.NormalShip}”/>

<f:selectItem

itemValue=”7”

itemLabel=”#{bundle.SaverShip}”/>

</h:selectOneMenu>

Пример соответствующего тегу свойства бина shippingOption:

private String shippingOption = "2"; // По умолчанию public void setShippingOption(String shippingOption) {

this.shippingOption = shippingOption;

}

public String getShippingOption() { return this.shippingOption;

}

Заметьте, что свойство shippingOption представляет выбранный к настоящему времени пункт из списка в компоненте SelectOne.

Компоненты SelectItem и SelectItems используются, чтобы задавать пункты в

компоненте SelectOne.

78

Свойство SelectItem

Компонент SelectItem представляет одно значение в наборе значений в ком-

поненте SelectMany или SelectOne. Компонент SelectItem может быть связанным со свойством внешнего бина типа SelectItem. Компонент SelectItem сформирован из объ-

екта, представляющего значение, и двух строк, представляющих этикетку и описание

объекта SelectItem.

Примера тега selectOneMenu содержит теги selectItem, которые устанавливают

строки списка пунктов на странице. Пример свойства бина, которое может установить значения для этого списка в бине:

SelectItem itemOne = null; SelectItem getItemOne(){ return itemOne;

}

void setItemOne(SelectItem item) { itemOne = item;

}

Свойство SelectItems

Компоненты SelectItems — потомки компонентов SelectMany и SelectOne.

Каждый компонент SelectItems состоит из множества экземпляров SelectItem или кол-

лекции объектов, как например, массив, список или даже таблица БД.

Свойства для SelectItems с объектами SelectItem

Вы можете заполнить SelectItems объектами SelectItem во внешнем бине:

1.Во внешнем бине создайте список, который связан с компонентом

SelectItem.

2.Определите множество объектов SelectItem, установите их значения и

заполните список объектами SelectItem.

Пример фрагмента кода внешнего бина, который показывает, как создать свой-

ство SelectItems:

import javax.faces.component.SelectItem;

...

protected ArrayList options = null;

protected SelectItem newsletter0 = // Новый элемент выбора new SelectItem("200", "Duke’s Quarterly", "");

... // Другие элементы выбора

//в конструкторе заполнить список элементов options.add(newsletter0); options.add(newsletter1); options.add(newsletter2);

...

//Свойство для первого элемента списка public SelectItem getNewsletter0(){

return newsletter0;

}

void setNewsletter0(SelectItem firstNL) { newsletter0 = firstNL;

79

}

...

// Другие свойства SelectItem public Collection[] getOptions(){

return options;

}

public void setOptions(Collection[] options){ this.options = new ArrayList(options);

}

Сначала код инициализирует опции как список. Каждое свойство newsletter задаётся некоторым значением и добавляется в список. Наконец, код включает обяза-

тельные методы доступа setOptions и getOptions для свойства options.

Запись свойств, связанных с компонентами

Связанные с экземплярами компонентов свойства возвращают и принимают

сами экземпляры компонент, а не данные от компонент. Следующие компоненты задаются свойством внешнего бина:

<h:selectBooleanCheckbox

id="fanClub"

rendered="false" binding=”#{cashier.specialOffer}"

/>

<h:outputLabel for="fanClub" rendered="false" binding="#{cashier.specialOfferText}" > <h:outputText id="fanClubLabel"

value="#{bundle.DukeFanClub}"

/>

</h:outputLabel>

Тег selectBooleanCheckbox отображается на странице переключателем и свя-

зывает компонент fanClub типа SelectBoolean со свойством specialOffer объекта

CashierBean. Тег outputLabel связывает компонент fanClubLabel (который отображает этикетку переключателя) со свойством specialOfferText бина класса CashierBean. Если пользователь заказывает покупку стоимостью более чем $100 и щёлкает кнопку Submit, то метод submit бина CashierBean устанавливает оба свойства rendered компонент в true, вызывая отображение текущего состояния переключателя и этикетки при

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

интерфейсов, настраиваемых на окружение пользователем.

Поскольку компоненты, соответствующие тегам примера, связаны со свойствами внешнего бина, эти свойства должны соответствовать типам компонент. Это озна-

чает, что свойство specialOfferText должно быть типа Output, а свойство specialOffer

должно быть типа SelectBoolean:

Output specialOfferText = ...;

public Output getSpecialOfferText() { // Дай компонент

80

return this.specialOfferText;

}

public void setSpecialOfferText(UIOutput specialOfferText) { this.specialOfferText = specialOfferText;

}

SelectBoolean specialOffer = ...;

public SelectBoolean getSpecialOffer() { // Дай компонент return this.specialOffer;

}

public void setSpecialOffer(UISelectBoolean specialOffer) { this.specialOffer = specialOffer;

}

Описание свойств связи с конвертерами, слушателями и проверками

Все стандартные преобразователи, слушатели и проверки включают поддержку

атрибута связи со свойствами внешних бинов. Работа с ними аналогична приведённо-

му ниже примеру.

Следующий пример показывает стандартный тег convertDateTime, использующийвыражение,чтобысвязатьэкземплярDateTimeConverter сосвойствомconvertDate

бина LoginBean:

<h:inputText value="#{LoginBean.birthDate}"> <f:convertDateTime binding="#{LoginBean.convertDate}" />

</h:inputText>

Следовательно, свойство convertDate должно принимать и возвращать объект класса DateTimeConverter, как показано здесь:

private DateTimeConverter convertDate;

public DateTimeConverter getConvertDate() {

...

return convertDate;

}

public void setConvertDate(DateTimeConverter convertDate) { convertDate.setPattern(“EEEEEEEE, MMM dd, yyyy”); this.convertDate = convertDate;

}

Поскольку преобразователь связан со свойством внешнего бина, свойство мо-

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

81

Соседние файлы в папке КСТ