Когда страница обращается к Managed-бину в первый раз, JavaServer Faces инициализирует его либо на основе аннотации @Named
и области видимости в классе компонента, либо в соответствии с конфигурацией в файле конфигурации приложения. Для получения информации об использовании аннотаций для инициализации бинов см. Использование аннотаций для настройки Managed-бинов.
Вы можете использовать аннотации или файл конфигурации приложения для создания объектов Managed-бинов, которые используются в приложении JavaServer Faces, и для сохранения их в области видимости. Средство создания Managed-бина настраивается в файле конфигурации приложения с использованием XML-элементов managed-bean
для определения каждого компонента. Этот файл обрабатывается во время запуска приложения. Для получения информации об использовании этого средства см. Использование элемента managed-bean.
Managed-бины, созданные в файле конфигурации приложения, управляются JavaServer Faces, но не CDI.
С помощью средства создания Managed-бина вы можете
-
Создавать бины в одном централизованном файле, который доступен всему приложению, а не создавайте условные объекты бинов по всему приложению
-
Настроить свойства бина без дополнительного кода
-
Настроить значения свойств компонента напрямую из файла конфигурации, чтобы он инициализировался этими значениями при его создании
-
Используя элементы value
, установить свойство одного Managed-бина в качестве результата вычисления другого выражения значения
Использование элемента managed-bean
Managed-бин инициируется в файле конфигурации приложения с помощью элемента managed-bean
, который представляет объект класса компонента, который должен существовать в приложении. Во время выполнения JavaServer Faces обрабатывает элемент managed-bean
. Если страница ссылается на компонент, а объект компонента не существует, JavaServer Faces создаёт объект компонента, как указано в конфигурации элемента.
Вот пример конфигурации Managed-бина из примера Duke's Bookstore:
<managed-bean eager="true">
<managed-bean-name>Book201</managed-bean-name>
<managed-bean-class>dukesbookstore.model.ImageArea</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>shape</property-name>
<value>rect</value>
</managed-property>
<managed-property>
<property-name>alt</property-name>
<value>Duke</value>
</managed-property>
<managed-property>
<property-name>coords</property-name>
<value>67,23,212,268</value>
</managed-property>
</managed-bean>
Элемент managed-bean-name
определяет ключ, под которым компонент будет храниться в области видимости. Чтобы значение компонента отображалось на этот бин, атрибут value
тега компонента должен соответствовать managed-bean-name
до первой точки.
Элемент managed-bean-class
определяет полное имя класса компонента JavaBeans, используемого для создания объекта бина.
Элемент managed-bean
может содержать ноль или более элементов managed-property
, каждый из которых соответствует свойству, определённому в классе бина. Эти элементы используются для инициализации значений свойств компонента. Если вы не хотите, чтобы конкретное свойство инициализировалось значением при создании объекта компонента, не включайте определение managed-property
для него в файл конфигурации приложения.
Если элемент managed-bean
не содержит других элементов managed-bean
, он может содержать один элемент map-entries
или list-entries
. Элемент map-entries
настраивает набор бинов, которые являются объектами Map
. Элемент list-entries
настраивает набор бинов, которые являются объектами List
.
В следующем примере Managed-бин newsletters
, представляющий компонент UISelectItems
, настроен как ArrayList
, представляющий набор объектов SelectItem
. Каждый объект SelectItem
в свою очередь настроен как Managed-бин со свойствами:
<managed-bean>
<managed-bean-name>newsletters</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value-class>javax.faces.model.SelectItem</value-class>
<value>#{newsletter0}</value>
<value>#{newsletter1}</value>
<value>#{newsletter2}</value>
<value>#{newsletter3}</value>
</list-entries>
</managed-bean>
<managed-bean>
<managed-bean-name>newsletter0</managed-bean-name>
<managed-bean-class>javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
<managed-property>
<property-name>label</property-name>
<value>Duke's Quarterly</value>
</managed-property>
<managed-property>
<property-name>value</property-name>
<value>200</value>
</managed-property>
</managed-bean>
...
Этот подход может быть полезен для быстрого создания списков выбора элементов до того, как группа разработчиков успеет создать такие списки из базы данных. Обратите внимание, что каждый из отдельных бинов рассылки имеет параметр managed-bean-scope
, равный none
, поэтому они сами не будут помещены в какую-либо область.
Инициализация свойств с использованием элемента managed-property
Элемент managed-property
должен содержать элемент property-name
, который должен соответствовать имени соответствующего свойства в бине. Элемент managed-property
также должен содержать один элемент из набора, который определяет значение свойства. Это значение должно быть того же типа, который определён для свойства в соответствующем компоненте. Какой элемент вы используете для определения значения, зависит от типа свойства, определённого в бине. Таблица 16-1 перечисляет все элементы, которые используются для инициализации значения.
Таблица 16-1. Подэлементы элементов управляемого свойства, которые определяют значения свойств
Элемент |
Какое значение определяет |
list-entries
|
Определяет значения в списке |
map-entries
|
Определяет значения отображения (Map) |
null-value
|
Явно устанавливает для свойства значение null |
value
|
Определяет одно значение, например выражение String , int или EL JavaServer Faces |
Использование элемента managed-bean включает в себя пример инициализации свойства int
(примитивного типа) с использованием дочернего элемента value
. Вы также можете использовать дочерний элемент value
для инициализации String
и других объектных типов. В оставшейся части этого раздела описано, как использовать дочерний элемент value
и другие дочерние элементы для инициализации свойств типов Java Enum
, Map
, array
и Collection
, а также параметры инициализации.
Ссылка на перечислимый тип Java (Enum)
Свойство Managed-бина также может иметь тип Java Enum
(см. http://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html
). В этом случае дочерний элемент value
элемента managed-property
должен быть String
, который соответствует одному из String
константы Enum
. Другими словами, String
должно быть одним из допустимых значений, которые могут быть возвращены, если вы вызовете valueOf(Class, String)
для enum
, где Class
— это класс Enum
, а String
— это содержимое дочернего элемента value
. Для примера предположим, что свойство Managed-бина является следующим:
public enum Suit { Hearts, Spades, Diamonds, Clubs }
...
public Suit getSuit() { ... return Suit.Hearts; }
Предполагая, что вы хотите настроить это свойство в файле конфигурации приложения, соответствующий элемент managed-property
выглядит следующим образом:
<managed-property>
<property-name>Suit</property-name>
<value>Hearts</value>
</managed-property>
Когда система сталкивается с этим свойством, она выполняет итерацию по каждому члену enum
и вызывает toString()
для каждого члена, пока не найдёт тот, который точно равен значению элемента value
.
Ссылка на контекстный параметр инициализации
Ещё одна мощная функция средства создания Managed-бина — это возможность ссылаться на неявные объекты из свойства Managed-бина.
Предположим, у вас есть страница, которая принимает данные от клиента, включая адрес клиента. Предположим также, что большинство ваших клиентов живут в городе с определённым кодом. Вы можете заставить компонент кода города отображать этот код, сохраняя его в неявном объекте и ссылаясь на него при отрисовке страницы.
Вы можете сохранить код города в качестве начального значения по умолчанию в неявном объекте контекста initParam
, добавив контекстный параметр в ваше веб-приложение и установив его значение в дескрипторе развёртывания. Например, чтобы задать контекстному параметру с именем defaultAreaCode
значение 650
, добавьте элемент context-param
в дескриптор развёртывания и присвойте параметру имя defaultAreaCode
и значение 650
.
Затем напишите объявление managed-bean
, которое настраивает свойство, ссылающееся на параметр:
<managed-bean>
<managed-bean-name>customer</managed-bean-name>
<managed-bean-class>CustomerBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>areaCode</property-name>
<value>#{initParam.defaultAreaCode}</value>
</managed-property>
...
</managed-bean>
Чтобы получить доступ к коду города во время отображения страницы, обратитесь к свойству из атрибута value
тега компонента area
:
<h:inputText id="area" value="#{customer.areaCode}"
Из других неявных объектов значения извлекаются аналогичным образом.
Инициализация свойств-отображений (Map)
Элемент map-entries
используется для инициализации значений свойства компонента с типом Map
, если элемент map-entries
используется внутри элемента managed-property
. Элемент map-entries
содержит необязательный элемент key-class
, необязательный элемент value-class
и ноль или более map-entry
.
Каждый из элементов map-entry
должен содержать элемент key
и элемент null-value
или value
. Вот пример, в котором используется элемент map-entries
:
<managed-bean>
...
<managed-property>
<property-name>prices</property-name>
<map-entries>
<map-entry>
<key>My Early Years: Growing Up on *7</key>
<value>30.75</value>
</map-entry>
<map-entry>
<key>Web Servers for Fun and Profit</key>
<value>40.75</value>
</map-entry>
</map-entries>
</managed-property>
</managed-bean>
Отображение, созданное этим тегом map-entries
, содержит две записи. По умолчанию все ключи и значения преобразуются в String
. Если вы хотите указать другой тип для ключей на карте, вставьте элемент key-class
прямо внутри элемента map-entries
:
<map-entries>
<key-class>java.math.BigDecimal</key-class>
...
</map-entries>
Это объявление преобразует все ключи в java.math.BigDecimal
. Конечно, вы должны убедиться, что ключи могут быть преобразованы в указанный тип. Ключ из примера в этом разделе не может быть преобразован в BigDecimal
, потому что это String
.
Если вы хотите указать другой тип для всех значений на карте, включите элемент value-class
после элемента key-class
:
<map-entries>
<key-class>int</key-class>
<value-class>java.math.BigDecimal</value-class>
...
</map-entries>
Обратите внимание, что этот тег устанавливает только тип всех подэлементов value
.
Каждая map-entry
в предыдущем примере включает в себя подэлемент value
. Подэлемент value
определяет одно значение, которое будет преобразовано в тип, указанный в бине.
Вместо использования элемента map-entries
также можно назначить всю карту, используя элемент value
, который задаёт выражение с типом карты.
Инициализация свойств-массивов и списков
Элемент list-entries
используется для инициализации значений массива или свойства List
. Каждое отдельное значение массива или List
инициализируется с использованием элемента value
или null-value
. Вот пример:
<managed-bean>
...
<managed-property>
<property-name>books</property-name>
<list-entries>
<value-class>java.lang.String</value-class>
<value>Web Servers for Fun and Profit</value>
<value>#{myBooks.bookId[3]}</value>
<null-value/>
</list-entries>
</managed-property>
</managed-bean>
В этом примере инициализируется массив или List
. Тип соответствующего свойства в компоненте определяет, какая структура данных создаётся. Элемент list-entries
определяет список значений в массиве или List
. Элемент value
указывает одно значение в массиве или List
и может ссылаться на свойство в другом бине. Элемент null-value
будет вызывать метод setBooks
с аргументом null
. Свойство null
нельзя указывать для свойства, тип данных которого является примитивом Java, например int
или boolean
.
Инициализация свойств Managed-бина
Иногда может понадобиться создать бин, который также ссылается на другие Managed-бины, чтобы можно было построить граф или дерево бинов. Для примера предположим, что вы хотите создать компонент, представляющий информацию о клиенте, включая почтовый адрес и адрес улицы, каждый из которых также является компонентом. Следующие объявления managed-bean
создают объект CustomerBean
, который имеет два свойства AddressBean
: одно представляет почтовый адрес, а другое — адрес улицы. Результатом этого объявления является дерево компонентов с CustomerBean
в качестве его родителя и двумя объектами AddressBean
в качестве дочерних.
<managed-bean>
<managed-bean-name>customer</managed-bean-name>
<managed-bean-class>
com.example.mybeans.CustomerBean
</managed-bean-class>
<managed-bean-scope> request </managed-bean-scope>
<managed-property>
<property-name>mailingAddress</property-name>
<value>#{addressBean}</value>
</managed-property>
<managed-property>
<property-name>streetAddress</property-name>
<value>#{addressBean}</value>
</managed-property>
<managed-property>
<property-name>customerType</property-name>
<value>New</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>addressBean</managed-bean-name>
<managed-bean-class>
com.example.mybeans.AddressBean
</managed-bean-class>
<managed-bean-scope> none </managed-bean-scope>
<managed-property>
<property-name>street</property-name>
<null-value/>
<managed-property>
...
</managed-bean>
Первое объявление CustomerBean
(с managed-bean-name
из customer
) создаёт CustomerBean
в области видимости запроса. Этот бин имеет два свойства: mailingAddress
и streetAddress
. Эти свойства используют элемент value
для ссылки на компонент с именем addressBean
.
Второе объявление Managed-бина определяет AddressBean
, но не создаёт его, потому что его элемент managed-bean-scope
определяет область видимости none
. Напомним, что область видимости none
означает, что компонент создаётся только тогда, когда на него ссылается что-то другое. Поскольку свойства mailingAddress
и streetAddress
ссылаются на addressBean
, используя элемент value
, два объекта AddressBean
создаются при создании CustomerBean
.
Когда вы создаёте объект, который указывает на другие объекты, не пытайтесь указывать на объект с более коротким сроком службы, потому что может быть невозможно восстановить ресурсы этой области видимости, когда объект будет удалён. Например, объект в области видимости сессии не может указывать на объект в области видимости запроса. А объекты с областью видимости none
не имеют чётко заданной продолжительности жизни, управляемой фреймворком, поэтому они могут указывать только на другие объекты с областью видимости none
. Таблица 16-2 описывает все разрешённые соединения.
Таблица 16-2. Допустимые соединения между объектами в области видимости
Объект этой области |
Может указывать на объект этой области |
none
|
none
|
application
|
none , application
|
session
|
none , application , session
|
request
|
none , application , session , request , view
|
view
|
none , application , session , view
|
Не допускайте циклических ссылок между объектами. Например, ни один из объектов AddressBean
в предыдущем примере не должен указывать на объект CustomerBean
, поскольку CustomerBean
уже указывает на AddressBean
объекты.
Инициализация отображений и списков
Помимо настройки свойств Map
и List
, вы также можете напрямую настроить Map
и List
, чтобы ссылаться на них из тега, а не через свойство, которое переносит Map
или List
.