Непосредственный атрибут в JSF обычно неправильно понимается. Если вы мне не верите, проверьте переполнение стека . Частичная путаница, вероятно, связана с тем, что они немедленно доступны как для входных (т.е. <h: inputText />), так и для командных (т. Е. <H: commandButton />) компонентов, каждый из которых по-разному влияет на жизненный цикл JSF.
Вот стандартный жизненный цикл JSF:
В этой статье я предполагаю, что вы знакомы с основами жизненного цикла JSF. Если вам нужно введение или обновление памяти, посмотрите Учебное пособие по Java EE 6 — Жизненный цикл приложения JavaServer Faces .
Примечание: примеры кода в этой статье предназначены для JSF 2 (Java EE 6), но принципы одинаковы для JSF 1.2 (Java EE 5).
немедленный = true для компонентов Command
В стандартном жизненном цикле JSF атрибут действия в компоненте Command оценивается на этапе вызова приложения . Например, скажем, у нас есть объект User / bean:
01
02
03
04
05
06
07
08
09
10
11
|
public class User implements Serializable { @NotBlank @Length (max = 50 ) private String firstName; @NotBlank @Length (max = 50 ) private String lastName; /* Snip constructors, getters/setters, a nice toString() method, etc */ } |
И UserManager, который будет служить нашим управляемым компонентом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@SessionScoped @ManagedBean public class UserManager { private User newUser; /* Snip some general page logic... */ public String addUser() { //Snip logic to persist newUser FacesContext.getCurrentInstance().addMessage( null , new FacesMessage( "User " + newUser.toString() + " added" )); return "/home.xhtml" ; } |
И базовая страница Facelets, newUser.xhtml , для визуализации представления:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
< h:form > < h:panelGrid columns = "2" > < h:outputText value = "First Name: " /> < h:panelGroup > < h:inputText id = "firstName" value = "#{userManager.newUser.firstName}" /> < h:message for = "firstName" /> </ h:panelGroup > < h:outputText value = "Last Name: " /> < h:panelGroup > < h:inputText id = "lastName" value = "#{userManager.newUser.lastName}" /> < h:message for = "lastName" /> </ h:panelGroup > </ h:panelGrid > < h:commandButton value = "Add User" action = "#{userManager.addUser()}" /> </ h:form > |
Которые все объединяются, чтобы произвести эту прекрасную форму:
Когда пользователь нажимает кнопку « Добавить пользователя» , на этапе Invoke Application будет вызван # {userManager.addUser} ; это имеет смысл, потому что мы хотим, чтобы поля ввода были проверены, преобразованы и применены к newUser до его сохранения.
Теперь давайте добавим кнопку «Отмена» на страницу, если пользователь передумает. Мы добавим еще одну <h: commandButton /> на страницу:
1
2
3
4
5
6
|
< h:form > <!-- Snip Input components --> < h:commandButton value = "Add User" action = "#{userManager.addUser()}" /> < h:commandButton value = "Cancel" action = "#{userManager.cancel()}" /> </ h:form > |
И метод cancel () для UserManager :
1
2
3
4
5
6
7
8
|
public String cancel() { newUser = new User(); FacesContext.getCurrentInstance().addMessage( null , new FacesMessage( "Cancelled new user" )); return "/home.xhtml" ; } |
Выглядит хорошо, правда? Но когда мы на самом деле пытаемся использовать кнопку отмены, мы получаем сообщения об ошибках, требующие ввода имени и фамилии:
Это связано с тем, что # {userManager.cancel} не вызывается до фазы вызова приложения , которая происходит после фазы проверки процесса ; так как мы не ввели имя и фамилию, проверки не прошли до вызова # {userManager.cancel} , а ответ будет обработан после фазы проверки процесса .
Мы, конечно, не хотим требовать от конечного пользователя ввести действительного пользователя перед отменой! К счастью, JSF предоставляет непосредственный атрибут для компонентов Command. Если для компонента Instant установлено значение true в компоненте Command, действие вызывается на этапе применения значений запроса :
Это идеально подходит для нашего варианта отмены. Если мы добавим немедленное = true в Cancel, # {userManager.cancel} будет вызван на этапе применения значений запроса , прежде чем произойдет какая-либо проверка.
1
2
3
4
5
6
|
< h:form > <!-- Snip Input components --> < h:commandButton value = "Add User" action = "#{userManager.addUser()}" /> < h:commandButton value = "Cancel" action = "#{userManager.cancel()}" immediate = "true" /> </ h:form > |
Поэтому теперь, когда мы нажимаем кнопку «Отмена», на этапе « Применить значения запроса» вызывается # {userManager.cancel} , и мы возвращаемся на домашнюю страницу с ожидаемым сообщением об отмене; нет ошибок проверки!
А как насчет компонентов ввода?
Входные компоненты также имеют непосредственный атрибут, который также перемещает всю их логику в фазу Применить значения запроса . Однако поведение немного отличается от компонентов Command, особенно в зависимости от того, успешно ли выполнена проверка на компоненте Input. Моя следующая статья будет посвящена немедленному = true для компонентов ввода. На данный момент, вот предварительный просмотр того, как затрагивается жизненный цикл JSF:
Ссылка: JSF и «непосредственный» атрибут — командные компоненты от нашего партнера JCG Джерри Орра из блога Jerry on Java .