Большинство веб-фреймворков Java были разработаны с учетом MVC; однако JSF, вероятно, является одним из немногих, кто достиг цели. Комбинируя JSF с JBoss Seam и Facelets, разработчик может реализовать шаблон проектирования MVC, используя:
- Бобы JBoss Seam POJO, представляющие модель данных
- Компоненты JBoss Seam, представляющие контроллер, где реализована бизнес-логика и где реализован уровень доступа к данным
- XHTML Facelets, представляющие вид
Это представляет собой истинную реализацию MVC, потому что bean-компонент JBoss Seam POJO действует как DTO, позволяя читать / записывать данные. Компонент действия JBoss Seam используется для манипулирования объектом данных, а фасеты XHTML отображают только те данные, которые «проталкиваются» в компоненты Seam.
Тем не менее, хотя теории, лежащие в основе MVC и модели JSF / Seam / Facelets, могут показаться очевидными, я видел, как разработчики часто злоупотребляют ими. Вот несколько распространенных ошибок, с которыми я столкнулся:
Сценарий 1 — Размещение кода инициализации контроллера в фасетах:
<s:div rendered="#{bean.init()}">
<h:outputText value="#{bean.text}"/>
</s:div>
Сценарий 2. Размещение методов поиска данных в фасетах:
<s:div>
<h:panelGroup rendered="#{bean.getAccountbyAccountNumber(accountNumber)}">
<h:outputText value="#{accountBean.firstname}"/>
<h:outputText value="#{accountBean.lastname}"/>
</h:panelGroup>
</s:div>
Сценарий 3 — Неправильное понимание жизненных циклов JSF и области применения JBoss Seam:
<s:div id="renderSection" rendered="#{bean.isVisible()}">
<h:outputText value="#{bean.text}"/>
<a4j:commandLink action="#{actionBean.retrieveBean()}" reRender="renderSection" />
</s:div>
… где бин был инициализирован через некоторые другие события, и у бина есть «Область действия».
ПРИМЕЧАНИЕ: указанная выше ссылка никогда не может быть «нажата», поскольку на этапе «восстановления представления» «renderSection» никогда не отображается.
6 жизненных циклов JSF
Понимание жизненных циклов JSF важно для разработчиков, чтобы правильно реализовать управляемый событиями JSF и частичное поведение рендеринга. JSF имеет 6 различных этапов:
(источник: учебное пособие по JEE )
- Восстановить вид
- Применить значения запроса; обрабатывать события
- Проверки процесса; обрабатывать события
- Обновить значения модели; обрабатывать события
- Вызвать приложение; обрабатывать события
- Предоставить ответ
На мой взгляд, восстановление представления — самая сложная фаза для понимания. На этапе восстановления представления это может быть новое представление или создаваемый постбэк:
- Новый вид создается и сохраняется в FaceContext, когда вы посещаете страницу в первый раз
- Обратная передача — это когда пользователь отправляет форму на существующую визуализированную страницу.
В сценарии 3, когда обработчик представления восстанавливает представление из FaceContext, ему будет не хватать значения bean-объекта Event Scope и, следовательно, остановлено выполнение.
Управляя всем от событий
В зависимости от того, насколько сложна логика при отображении страницы, вы можете решить, следует ли использовать шаблон, описанный ниже. Давайте посмотрим на пример макета ниже
Это простая веб-страница почтового ящика, и обратите внимание, что всякий раз, когда вы выбираете вкладку слева: входящие, исходящие, контакты … и т. Д., Или выбираете другую учетную запись из раскрывающегося списка учетных записей, дерева папок, списка писем и содержимого просмотров почты должны быть обновлены. Очевидно, мы могли бы реализовать это, имея
<h:selectOneMenu id="account" value="#{accountBean.selectedAccount}">
<f:selectItem itemValue="Select an account...."/>
<f:selectItems value="#{accountBean.validAccounts}"/>
<a4j:support event="onchange" actionListener="#{accountSelectAction.selectOneAccount}"
reRender="mailPanel" ajaxSingle="true"/>
</h:selectOneMenu>
… и в методе selectOneAccount реализуется следующая логика:
- Получить список папок
- Установить папки по умолчанию
- Получить список писем в папке
- Установите отображение почты по умолчанию
- Получить содержимое почты
Гораздо более элегантное решение заключается в реализации:
Event.raiseEvent("ReloadFoldersEvent");Event.raiseEvent("ReloadFoldersEvent");
…. и прослушиватель метода RetrieveFolders для прослушивания ReloadFoldersEvent . Как только поиск в папке будет завершен, мы хотим вызвать другое событие в методе, чтобы вызвать получение почты:
Event.raiseEvent("ReloadMailsEvent");
Повторите этот шаблон для метода RetrieveMails (ReloadMailContentsEvent) и метода RetrieveMailContent .
Повышая значения параметров ReloadFoldersEvent, ReloadMailsEvent, ReloadMailContentsEvent и прослушивая события в контроллерах Seam, можно избежать многократного создания очень похожей логики в методах контроллера RetrieveFolders, RetrieveMails и RetrieveMailContents .
Более того, правильный MVC достигается за счет того, что методы RetrieveFolders, RetrieveMails и RetrieveMailContents (Controller) могут заполнять фасоли значений (Model) в событиях, а facelets (View) требуется ТОЛЬКО для взаимодействия с фасолями значений для заполнения пользовательского интерфейса.
От Коле Enterprise Consulting блог
#{bean.init()}