Область действия сеанса существует в нескольких циклах запросов-ответов HTTP (теоретически неограниченно).
Область запросов очень полезна в любом веб-приложении, когда требуется одно взаимодействие на цикл HTTP-запрос-ответ. Однако, когда вам нужны объекты, видимые для любого цикла HTTP-запроса-ответа, принадлежащего сеансу пользователя, тогда вам нужна область сеанса ; в этом случае bean-компонент живет столько же, сколько и HTTP-сеанс. Область действия сеанса позволяет создавать и привязывать объекты к сеансу. Он создается при первом HTTP-запросе с участием этого компонента в сеансе и уничтожается при аннулировании сеанса HTTP. Область запроса присутствует в JSF и CDI и функционирует аналогичным образом. Он может быть использован для не насыщенных запросов AJAX и не AJAX.
Аннотации для сессий
JSF : аннотацией области действия запроса JSF является @SessionScoped ( javax.faces.bean.SessionScoped ). @ManagedBean с этой областью действия должен быть аннотирован @ManagedBean ( javax.faces.bean.ManagedBean ). Область по умолчанию — @RequestScope .
CDI : аннотацией области действия запроса CDI является @SessionScoped ( javax.enterprise.context.SessionScoped ). @Named с такой областью действия должен быть аннотирован @Named ( javax.inject.Named ). Для управляемых компонентов CDI ( @Named ) @Named по умолчанию является псевдо-область @Dependent .
Простой пример
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
// index.xhtml<h:body> <h4>Same view after submit (index.xhtml):</h4> <h:form> <h:commandButton value="Count" action="#{countBean.countActionVoid()}"/> </h:form> Current value: #{countBean.count} <h4>Forward to another view after submit (count.xhtml):</h4> <h:form> <h:commandButton value="Count" action="#{countBean.countActionAndForward()}"/> </h:form> Current value: #{countBean.count} <h4>Redirect to another view after submit (count.xhtml):</h4> <h:form> <h:commandButton value="Count" action="#{countBean.countActionAndRedirect()}"/> </h:form> Current value: #{countBean.count} <h4>AJAX :</h4> <h:form> <h:commandButton value="Count" action="#{countBean.countActionVoid()}"> <f:ajax render="currentValueId"/> </h:commandButton> </h:form> <h:outputText id="currentValueId" value="Current value: #{countBean.count}"/></h:body>// count.xhtml<h:body> Current value: #{countBean.count} </h:body>// CountBean.javaimport java.util.logging.Logger;import java.io.Serializable;// for JSFimport javax.faces.bean.ManagedBean;import javax.faces.bean.SessionScoped;// for CDIimport javax.inject.Named;import javax.enterprise.context.SessionScoped;// JSF vs CDI@ManagedBean @Named@SessionScoped @SessionScopedpublic class CountBean implements Serializable { private static final Logger LOG = Logger.getLogger(CountBean.class.getName()); private int count; public CountBean() { LOG.info("CountBean#Initializing counter ..."); count = 0; } public void countActionVoid() { LOG.info("CountBean#countActionVoid() - Increasing counter ..."); count++; } public String countActionAndForward() { LOG.info("CountBean#countActionAndForward() - Increasing counter ..."); count++; return "count"; } public String countActionAndRedirect() { LOG.info("CountBean#countActionAndRedirect() - Increasing counter ..."); count++; return "count?faces-redirect=true;"; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } } |
Полное приложение доступно здесь .
Таким образом, при навигации через AJAX, через механизм пересылки назад в том же виде (или другом виде) или механизме перенаправления значение count будет увеличено на 1 . Это раскрывает два аспекта:
- Конструктор
CountBeanвызывается для создания нового экземпляра один раз за сеанс пользователя. Это означает, чтоcountинициализируется с0только один раз. Дальнейшие запросы, запущенные в текущем сеансе пользователя, будут использовать этот экземплярCountBean. Мы говорим, что для каждого пользователяCountBeanэкземплярCountBean. - Область сеанса не теряет состояние объекта при пересылке или перенаправлении. Состояние объекта доступно до тех пор, пока
sessionбудет уничтожен (например, время ожидания сеанса, недействительность и т. Д.).
В основном вы должны обращать внимание, когда вы отправляете данные в сессионный компонент. Представленные данные будут «жить» столько, сколько текущий пользовательский сеанс. Итак, хорошая практика скажет вам не хранить в сеансе большое количество данных, особенно если память является критическим ресурсом.
Реализует Сериализуемый
Управляемые компоненты JSF и CDI должны быть объявлены как Serializable ( implements Serializable ). Это необходимо, поскольку контейнер может сохранить (сериализовать) данные сеанса на жесткий диск. Это позволяет контейнеру управлять критическими ситуациями, такими как тяжелая загрузка, или просто обмениваться данными с другими серверами в кластере или восстанавливать сеансы во время перезапуска сервера.
Session Scope Программный доступ
Программно вы можете взаимодействовать с областью сеанса следующим образом:
- получить доступ к карте области сеанса
0102030405060708091011
// JSF 2.0-2.2FacesContext context = FacesContext.getCurrentInstance();Map<String, Object> requestMap = context.getExternalContext().getSessionMap();// JSF 2.3@Inject@SessionMapprivateMap<String, Object> sessionMap;// OmniFacesMap<String, Object> requestmap = Faces.getSessionMap(); - получить атрибут области сеанса
12345
// JSF 2.0 - 2.3sessionMap.put(name, value);// OmniFacesFaces.setSessionAttribute(name, value); - удалить атрибут области сеанса
12345
// JSF 2.0-2.3Object value = sessionMap.remove(name);// OmniFaces<T> value = Faces.removeSessionAttribute(name);
! На страницах JSF вы можете использовать неявный объект #{sessionScope} (например, получить экземпляр CountBean : #{sessionScope.countBean} ).
Среди прочего, карта сеанса будет содержать экземпляры управляемых bean-компонентов, объявленных в области сеанса ( @SessionScoped (JSF/CDI )).
В случае JSF-управляемых bean-компонентов (не CDI-управляемых bean-компонентов — в этом случае ключи довольно сложны), вы можете легко идентифицировать такие bean-компоненты по их именам, которые становятся ключами в карте сеанса. Поэтому вы сможете найти экземпляр этого управляемого JSF-компонента в карте сеанса под ключом countBean . Если вы указываете имя компонента через @ManagedBean (name = » some_name «), то some_name будет ключом в карте сеанса. Таким образом, с помощью карты сеансов вы можете получить доступ к свойству управляемого JSF-компонента в рамках сеанса, например:
|
1
|
String count = ((CountBean)(Faces.getSessionAttribute("countBean/some_name"))).getCount(); |
Совершенно законно также делать это (это относится к текущему компоненту):
|
1
2
3
4
|
@ManagedBean(name="some_name")...String bean_name = getClass().getAnnotation(ManagedBean.class).name();int count = ((CountBean)(Faces.getSessionAttribute(bean_name))).getCount(); |
Теперь вы можете легко понять, как работать с управляемыми bean-компонентами, хранящимися в карте сеанса.
Использование @PostConstruct
Как правило, в управляемом bean-компоненте нам нужно написать метод, аннотированный @PostConstruct для выполнения задач инициализации на основе введенных артефактов. Другими словами, аннотация @PostConstruct используется для метода, который должен быть выполнен после внедрения зависимости для выполнения любой инициализации. Когда инициализация не включает в себя введенные артефакты, конструктор может использоваться для инициализации. Для bean- @PostConstruct действия метод, аннотированный @PostConstruct будет вызываться только один раз после создания экземпляра bean- @PostConstruct области действия.
Пример управляемого компонента JSF:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import java.io.Serializable;import javax.faces.bean.ManagedBean;import javax.faces.bean.SessionScoped;@ManagedBean@SessionScopedpublic class InitBean implements Serializable{ private int init; public InitBean() { init = 5; } public int getInit() { return init; } public void setInit(int init) { this.init = init; }}import java.io.Serializable;import javax.faces.bean.ManagedBean;import javax.faces.bean.SessionScoped;@ManagedBean@SessionScopedpublic class CountBean implements Serializable { @ManagedProperty("#{initBean}") private InitBean initBean; @PostConstruct public void init(){ LOG.info("CountBean#Initializing counter with @PostConstruct ..."); count = initBean.getInit(); } public void setInitBean(InitBean initBean) { this.initBean = initBean; } ...} |
Пример управляемого компонента CDI:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
import java.io.Serializable;import javax.enterprise.context.SessionScoped;import javax.inject.Named;@Named@SessionScopedpublic class InitBean implements Serializable { private int init; public InitBean() { init = 5; } public int getInit() { return init; } public void setInit(int init) { this.init = init; }}import java.io.Serializable;import javax.inject.Inject;import javax.enterprise.context.SessionScoped;import javax.inject.Named;@Named@SessionScopedpublic class CountBean implements Serializable { @Inject private InitBean initBean; @PostConstruct public void init(){ LOG.info("CountBean#Initializing counter with @PostConstruct ..."); count = initBean.getInit(); } ...} |
Инъекционные и сессионные бобы
JSF : Для управляемых компонентов JSF внедрение осуществляется через @ManagedProperty . Например:
CDI : для управляемых компонентов CDI внедрение осуществляется через @Named . Например:
Смешанный JSF и CDI: CDI может быть введен в JSF (наоборот, это не так!)
JSF Managed Beans Ограничения:
! Как правило, в JSF не используйте объекты с более коротким сроком службы, чем объекты, из которых вы их вызываете. Другими словами, используйте объекты, у которых продолжительность жизни такая же или больше, чем у объекта, который вводится. Нарушение этого правила приведет к исключению JSF. Основываясь на этом правиле, в управляемом bean-объекте области действия JSF можно вводить управляемые bean-компоненты сеанса и приложения, но не запрашивать или просматривать управляемые bean-компоненты. Управляемые компоненты JSF могут быть внедрены в другие управляемые компоненты JSF.
Ограничения CDI Managed Beans:
! Когда вы используете объект с более коротким сроком службы, чем у объекта, из которого вы его вызываете (например, вставка bean-объекта с областью запроса в bean-объект сессионного объекта), CDI классифицирует случай использования как несоответствующее внедрение и исправляет проблему через CDI прокси. Для каждого запроса прокси-сервер CDI повторно устанавливает соединение с действующим экземпляром bean-объекта области действия запроса. Управляемые компоненты CDI могут быть внедрены в управляемые компоненты JSF.
Конфигурирование управляемых bean-компонентов JSF-сессии программным способом
Начиная с JSF 2.2, мы можем программно воспроизводить содержимое faces-config.xml . Для управляемых bean-компонентов сессионной области соответствующий фрагмент кода:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Overridepublic void populateApplicationConfiguration (Document toPopulate) { String ns = toPopulate.getDocumentElement().getNamespaceURI(); Element managedbeanEl = toPopulate.createElementNS(ns, "managed-bean"); Element managedbeannameEl = toPopulate.createElementNS(ns, "managed-bean-name"); managedbeannameEl.appendChild(toPopulate.createTextNode("countBean")); managedbeanEl.appendChild(managedbeannameEl); Element managedbeanclassEl = toPopulate.createElementNS(ns, "managed-bean-class"); managedbeanclassEl.appendChild(toPopulate.createTextNode("beans.CountBean")); managedbeanEl.appendChild(managedbeanclassEl); Element managedbeanscopeEl = toPopulate. createElementNS(ns, "managed-bean-scope"); managedbeanscopeEl.appendChild(toPopulate. createTextNode("session")); managedbeanEl.appendChild(managedbeanscopeEl); ... // programmatic create managed-property ... toPopulate.getDocumentElement().appendChild(managedbeanEl);} |
Полное приложение можно увидеть в книге Mastering JSF 2.2 .
Конфигурирование управляемых bean-объектов JSF-запроса в XML-файле
В конфигурации XML вы можете использовать старый механизм JSF 1.x для определения управляемого компонента в обычном файле faces-config.xml . Например:
|
01
02
03
04
05
06
07
08
09
10
|
...<managed-bean> <managed-bean-name>countBean</managed-bean-name> <managed-bean-class>beans.CountBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> ... <!-- managed bean properties --> via <managed-property/> ...</managed-bean>... |
Управляемые bean-компоненты должны быть определены в отдельном XML-файле, так как faces-config.xml используется для настройки конфигурации уровня приложения. По сути, если вы предпочитаете такой подход, создайте новый XML-файл и поместите в него детали управляемых компонентов. Наконец, объявите файл XML с помощью параметра контекста javax.faces.CONFIG_FILES в файле web.xml .
|
1
2
3
4
5
6
|
...<context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>WEB-INF/my-manage-beans.xml</param-value></context-param>... |
Увидимся в следующем посте о сфере применения JSF / CDI.
| Ссылка: | Учебное пособие по JSF — Session Scope Scope от нашего партнера JCG Ангела Леонарда в блоге JSF и поклонников OmniFaces . |





