Як правильно вибрати область бобів?


381

Я помітив, що існують різні види квасолі:

@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped

Яке призначення кожного? Як вибрати правильну область застосування для квасолі?


Відповіді:


485

Вступ

Він представляє обсяг (термін експлуатації) квасолі. Це простіше зрозуміти, якщо ви знайомі з роботою базового веб-додатку сервлетів "під прикриттями": Як працюють сервлети? Моменталізація, сеанси, загальні змінні та багатопотоковість .


@Request/View/Flow/Session/ApplicationScoped

@RequestScopedБоб живе до тих пір , як цикл запиту-відповіді одного HTTP (зверніть увагу , що розраховує запит Ajax як одного запиту HTTP теж). @ViewScopedБоб живе до тих пір , поки ви взаємодіючи з тим же точкою зору JSF по постбека , які методи дій виклику повертаються null/ voidбез навігації / редиректу. @FlowScopedБоб живе до тих пір , поки ви переміщаючись по заданій колекції уявлень , зареєстрованих в файлі конфігурації потоку. @SessionScopedБоб живе до тих пір, встановленої HTTP сесії. @ApplicationScopedБоб живе до тих пір , як біжить веб - додатків. Зверніть увагу , що КДІ @Modelв основному стереотип для @Named @RequestScoped, так само правила.

Яку сферу вибору вибрати, залежить виключно від даних (штату), які має боб Використовуйте @RequestScopedдля простих та не-аяксних форм / презентацій. Використовуйте @ViewScopedдля розширених динамічних представлень з підтримкою функціональних можливостей ajax (перевірка на основі придатних знаків, візуалізація, діалоги тощо). Використовуйте @FlowScopedдля шаблону "майстра" ("анкетування") збирання вхідних даних, що поширюються на декілька сторінок. Використовуйте @SessionScopedдля конкретних клієнтів даних, таких як зареєстровані користувачі та налаштування користувача (мова тощо). Використовуйте @ApplicationScopedдля даних / констант для широкого застосування, такі як спадні списки, які однакові для всіх, або керовані боби без будь-яких змінних екземплярів та мають лише методи.

Зловживання @ApplicationScopedbean для даних, пов’язаних із сеансом / переглядом / запитом, дозволить їм ділитися між усіма користувачами, тому будь-хто інший може бачити дані один одного, що просто неправильно. Зловживання @SessionScopedbean для перегляду / запиту масштабованих даних дозволить ділитися між усіма вкладками / вікнами за один сеанс браузера, тому кінцевий користувач може зазнати неузгодженості під час взаємодії з кожним переглядом після переключення між вкладками, що погано для роботи користувачів. Зловживання @RequestScopedbean для перегляду масштабованих даних призвело б до повторної ініціалізації даних перегляду для перегляду за замовчуванням у кожному окремому зворотному режимі (ajax), викликаючи, можливо, непрацюючі форми ( див. Також пункти 4 та 5 тут ). Зловживання @ViewScopedbean для запиту, сеансу чи застосування програми, а також зловживання a@SessionScoped bean для даних, пов’язаних з обсягами додатків, не впливає на клієнта, але він зайво займає пам'ять сервера і є просто неефективним.

Зауважте, що сферу застосування не слід вибирати, виходячи із наслідків для продуктивності, якщо ви справді не маєте низького сліду пам’яті та не хочете повністю втратити стан; вам потрібно буде використовувати виключно @RequestScopedквасолі та скрипки з параметрами запиту, щоб підтримувати стан клієнта. Також зауважте, що якщо у вас є одна сторінка JSF з різними масштабами даних, то цілком справедливо розміщувати їх у окремій резервній квасолі в області, що відповідає обсягу даних. Квасоля може просто отримати доступ один до одного, @ManagedPropertyякщо це боби, керовані JSF, або @Injectдля бобів, які керуються CDI.

Дивись також:


@CustomScoped/NoneScoped/Dependent

Це не згадується у вашому питанні, але (спадщина) JSF також підтримує @CustomScopedі @NoneScoped, які рідко використовуються в реальному світі. @CustomScopedПовинен звернутися призначений для користувача Map<K, Bean>реалізації в деякій широкої області , яка має змінені Map#put()і / або Map#get()для того , щоб мати більш дрібнозернистий контроль над створенням бобу і / або знищити.

JSF @NoneScopedта CDI в @Dependentосновному живе до тих пір, як єдина оцінка EL на зернах. Уявіть форму для входу з двома полями введення, що посилаються на властивість bean, та командною кнопкою, що посилається на дію bean, таким чином, усього три вирази EL, тоді ефективно будуть створені три екземпляри. Один із набором імені користувача, один із встановленим паролем та той, на який викликається дія. Зазвичай ви хочете використовувати цю сферу застосування лише на квасолі, яка повинна жити до тих пір, як квасоля, де її вводять. Отже, якщо a @NoneScopedабо @Dependentвводиться в a @SessionScoped, він буде жити до тих пір, поки @SessionScopedквасоля.

Дивись також:


Область Flash

Як останнє, JSF також підтримує область спалаху. Він підтримується коротким файлом cookie, який пов’язаний із введенням даних у область сеансу. Перед перенаправленням на HTTP-відповідь буде встановлено файл cookie зі значенням, яке однозначно пов'язане з введенням даних у область сеансу. Після переадресації перевірятиметься наявність файлу cookie флеш-області, а введення даних, пов’язане з файлом cookie, буде видалено з області сеансу та буде розміщено в області запиту переспрямованого запиту. Нарешті файл cookie буде видалено з відповіді HTTP. Таким чином, перенаправлений запит має доступ до даних, що охоплюються, які були підготовлені в початковому запиті.

Це насправді недоступно як керована область бобів, тобто немає такого поняття, як @FlashScoped. Область спалаху доступна лише у вигляді карти через ExternalContext#getFlash()керовані боби та #{flash}EL.

Дивись також:


4
Я думаю, посилання на вашу відповідь на запитання " Як і коли знищується область видимості в JSF? " Тут є доречною.
Лій

3
@Cold: це стара область CDI і в JSF 2.2 замінена @FlowScoped(не потрібно вручну запускати / зупиняти її).
BalusC

1
А DeltaSpike додатково має ViewAccesscopedіWindowScoped
Kukeltje

@BalusC, я думаю, що ViewScopedв MyFaces 2.2 виникла проблема. На даний момент я стикаюся з проблемою з ViewScopedбобом та Ajax, яку я опублікував тут . У програмі MyFaces JIRA також йде дискусія на цю тему.
Тапас Босе

CDI визначає чотири вбудовані області застосування: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped чому сфери, які ви описуєте, відрізняються?
Хосейн Акаджані

122

Починаючи з JSF 2.3, усі сфери застосування бобів, визначені в пакетній javax.faces.beanупаковці, були зняті, щоб вирівняти область застосування з CDI. Більше того, вони застосовуються лише в тому випадку, якщо ваш боб використовує @ManagedBeanанотацію. Якщо ви використовуєте версії JSF нижче 2.3, зверніться до застарілої відповіді в кінці.


З JSF 2.3 ось сфери застосування, які можна використовувати на підставних бобах JSF:

1@javax.enterprise.context.ApplicationScoped .: Обсяг програми зберігається протягом усієї тривалості веб-програми. Цей обсяг ділиться між усіма запитами та всіма сесіями. Це корисно, коли у вас є дані для цілої програми.

2@javax.enterprise.context.SessionScoped .: Обсяг сеансу зберігається з моменту встановлення сеансу до завершення сеансу. Контекст сеансу поділяється між усіма запитами, що виникають в одному сеансі HTTP. Це корисно, коли ви не бажаєте зберігати дані для конкретного клієнта для певного сеансу.

3. @javax.enterprise.context.ConversationScoped .: Обсяг розмови зберігається як журнал, коли живе боб. Область застосування передбачає 2 способи: Conversation.begin()та Conversation.end(). Ці методи слід чітко закликати або розпочати або закінчити життя бобових.

4@javax.enterprise.context.RequestScoped .: Обсяг запиту короткочасний. Він починається після надсилання запиту HTTP і закінчується після того, як відповідь буде відправлена ​​назад клієнту. Якщо ви розмістите керований боб у область запиту, з кожним запитом створюється новий екземпляр. Варто розглянути область запиту, якщо вас турбує вартість зберігання обсягу сеансу.

5. @javax.faces.flow.FlowScoped .: Обсяг потоку зберігається, поки живе Потік. Потік може бути визначений як міститься набір сторінок (або переглядів), які визначають одиницю роботи. Потоковий обсяг був активним до тих пір, поки користувач переходить у Потік.

6. @javax.faces.view.ViewScoped .: Зображення в області перегляду зберігається, коли та сама сторінка JSF повторно відображається. Як тільки користувач переходить на іншу сторінку, боб виходить із сфери застосування.


Наступна застаріла відповідь стосується версії JSF до 2.3

Станом на JSF 2.x є 4 сфери застосування:

  • @SessionScoped
  • @RequestScoped
  • @ApplicationScoped
  • @ViewScoped

Обсяг сеансу: Обсяг сеансу зберігається з моменту встановлення сеансу до завершення сеансу. Сеанс припиняється, якщо веб-додаток викликає недійсний метод на об’єкті HttpSession або якщо він закінчується.

RequestScope: Обсяг запиту короткочасний. Він починається після надсилання запиту HTTP і закінчується після того, як відповідь буде відправлена ​​назад клієнту. Якщо ви розмістите керований боб у область запиту, з кожним запитом створюється новий екземпляр. Варто розглянути область запиту, якщо вас турбує вартість зберігання обсягу сеансу.

ApplicationScope: область застосування зберігається протягом усієї тривалості веб-програми. Цей обсяг ділиться між усіма запитами та всіма сесіями. Ви розміщуєте керовані боби в області застосування, якщо один боб повинен бути спільним для всіх примірників веб-програми. Бін будується, коли його вперше запитує будь-який користувач програми, і він залишається живим, поки веб-додаток не буде видалено з сервера додатків.

ViewScope: область перегляду була додана в JSF 2.0. Зображення в області перегляду зберігається під час повторного відображення тієї ж сторінки JSF. (Специфікація JSF використовує перегляд терміна для сторінки JSF.) Як тільки користувач переходить на іншу сторінку, боб виходить із сфери застосування.

Вибирайте сферу застосування, виходячи зі своєї вимоги.

Джерело: Core Java Faces 3rd Edition від David Geary & Cay Horstmann [Стор. № 51 - 54] введіть тут опис зображення


Чи можете ви пояснити, що ви маєте на увазі під методом недійсного об'єкта HttpSession: invalidate()методом чи недійсним методом?
Олександр Позднеєв

1
Трохи старий і, можливо, запізнився на відповідь, але для уточнення цього: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();це означає, що його викликають у вашому "бобі виходу".
Roland

1
це стало спадковою відповіддю, на даний момент існує 8 областей
Ewoks

@KishorPrakash: деякий час зараз 6 місяців тому. ;-)
Kukeltje

@Kukeltje: Вибачте, я на цьому.
Кішор Пракаш
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.