Jak wybrać odpowiedni zakres fasoli?

Odpowiedzi:

485

Wprowadzenie

Reprezentuje zakres (czas życia) fasoli. Łatwiej to zrozumieć, jeśli znasz podstawową aplikację internetową serwletu: jak działają serwlety? Tworzenie instancji, sesje, zmienne współdzielone i wielowątkowość .


@Request/View/Flow/Session/ApplicationScoped

@RequestScopedFasola żyje tak długo, jak w cyklu żądanie-odpowiedź HTTP pojedynczy (zauważ, że żądania Ajax liczy się jako jedno żądanie HTTP zbyt). @ViewScopedFasola żyje tak długo, jak jesteś interakcji z tego samego widoku JSF przez postbacks jakie metody działania wezwanie powracających null/ voidbez nawigacji / przekierowania. @FlowScopedMieszka fasoli Dopóki jesteś przechodząc przez określony zbiór poglądów zarejestrowane w pliku konfiguracyjnym przepływu. @SessionScopedFasola żyje tak długo, jak długo sesji HTTP siedzibę. @ApplicationScopedFasola żyje tak długo, jak działa aplikacja internetowa. Należy zauważyć, że CDI @Modeljest w zasadzie stereotypu za @Named @RequestScoped, więc stosuje się te same zasady.

Wybór zakresu zależy wyłącznie od danych (stanu), które fasola przechowuje i reprezentuje. Użyj @RequestScopeddo prostych formularzy / prezentacji innych niż ajax. Użyj @ViewScopeddla bogatych widoków dynamicznych z włączonym systemem ajax (sprawdzanie poprawności, renderowanie, okna dialogowe itp.). Użyj @FlowScopeddo wzorca „kreatora” („kwestionariusza”) zbierania danych wejściowych rozłożonych na wielu stronach. Używaj @SessionScopeddo danych specyficznych dla klienta, takich jak zalogowany użytkownik i preferencje użytkownika (język itp.). Używaj @ApplicationScopeddo danych / stałych dla całej aplikacji, takich jak listy rozwijane, które są takie same dla wszystkich, lub zarządzanych komponentów bean bez zmiennych instancji i posiadających tylko metody.

Nadużywanie komponentu @ApplicationScopedbean dla danych o zasięgu sesji / widoku / żądania spowodowałoby, że byłoby ono dzielone między wszystkich użytkowników, dzięki czemu każdy mógł zobaczyć dane innych użytkowników, co jest po prostu błędne. Nadużywanie komponentu @SessionScopedbean dla danych o zasięgu / żądaniach spowodowałoby, że byłby on współużytkowany przez wszystkie karty / okna w jednej sesji przeglądarki, więc użytkownik końcowy może doświadczyć niespójności podczas interakcji z każdym widokiem po przełączeniu między kartami, co jest niekorzystne dla wygody użytkownika. Nadużywanie komponentu @RequestScopedbean dla danych o zasięgu wyświetlania sprawiłoby, że dane o zasięgu widzenia byłyby ponownie inicjowane do wartości domyślnych przy każdym pojedynczym odsyłaniu zwrotnym (ajax), powodując prawdopodobnie niedziałające formularze ( patrz także punkty 4 i 5 tutaj ). Nadużywanie komponentu @ViewScopedbean dla danych o zasięgu żądania, sesji lub aplikacji oraz nadużywanie@SessionScoped komponent bean dla danych o zasięgu aplikacji nie wpływa na klienta, ale niepotrzebnie zajmuje pamięć serwera i jest po prostu nieefektywny.

Zauważ, że zakres raczej nie powinien być wybierany na podstawie wpływu na wydajność, chyba że naprawdę masz mało pamięci i chcesz przejść całkowicie bezstanowo; musisz użyć wyłącznie @RequestScopedfasoli i skrzypce z parametrami żądania, aby utrzymać stan klienta. Należy również pamiętać, że jeśli masz jedną stronę JSF z danymi o różnym zakresie, to jest całkowicie poprawne umieszczenie ich w osobnych komponentach bean backing w zakresie pasującym do zakresu danych. Fasola może po prostu uzyskiwać do siebie dostęp @ManagedPropertyw przypadku fasoli zarządzanej przez JSF lub @Injectw przypadku fasoli zarządzanej przez CDI.

Zobacz też:


@CustomScoped/NoneScoped/Dependent

Nie wspomniano o tym w twoim pytaniu, ale (starsze) JSF obsługuje również @CustomScopedi @NoneScoped, które są rzadko używane w prawdziwym świecie. @CustomScopedMusi odnosić niestandardową Map<K, Bean>implementację w jakimś szerszym zakresie, który nadpisuje Map#put()i / lub Map#get()w celu uzyskania bardziej drobnoziarnista kontrolę nad tworzeniem fasoli i / lub zniszczyć.

JSF @NoneScopedi CDI @Dependentzasadniczo żyją tak długo, jak jedna ocena EL na fasoli. Wyobraź sobie formularz logowania z dwoma polami wejściowymi odnoszącymi się do właściwości komponentu bean i przyciskiem polecenia odnoszącym się do akcji komponentu bean, a więc z łącznie trzema wyrażeniami EL, a następnie utworzone zostaną trzy instancje. Jeden z ustawioną nazwą użytkownika, jeden z ustawionym hasłem i jeden, na którym wywoływana jest akcja. Zwykle chcesz używać tego lunety tylko na fasoli, która powinna żyć tak długo, jak fasola, w której jest wstrzykiwana. Więc jeśli a @NoneScopedlub @Dependentzostanie wstrzyknięty w a @SessionScoped, to będzie żył tak długo, jak @SessionScopedfasola.

Zobacz też:


Luneta błyskowa

Na koniec JSF obsługuje także zakres flashowania. Jest on wspierany przez krótkotrwały plik cookie, który jest powiązany z wprowadzaniem danych w zakresie sesji. Przed przekierowaniem zostanie ustawiony plik cookie w odpowiedzi HTTP o wartości, która jest jednoznacznie związana z wprowadzaniem danych w zakresie sesji. Po przekierowaniu zostanie sprawdzona obecność pliku cookie zakresu flash, a dane powiązane z plikiem cookie zostaną usunięte z zakresu sesji i zostaną umieszczone w zakresie żądania przekierowanego żądania. Wreszcie plik cookie zostanie usunięty z odpowiedzi HTTP. W ten sposób przekierowane żądanie ma dostęp do danych o zasięgu, które zostały przygotowane w pierwszym żądaniu.

W rzeczywistości nie jest to dostępne jako zarządzany zakres komponentu bean, tzn. Nie ma czegoś takiego jak @FlashScoped. Luneta jest dostępna tylko jako mapa ExternalContext#getFlash()w zarządzanej fasoli i #{flash}w EL.

Zobacz też:

BalusC
źródło
4
Myślę, że odniesienie do twojej odpowiedzi na pytanie „ Jak i kiedy jest zniszczona fasola zakresu widoku w JSF? ” Jest tutaj istotne.
Lii
3
@Cold: to stary zakres CDI, w JSF 2.2 zastąpiony @FlowScoped(nie ma potrzeby ręcznego uruchamiania / zatrzymywania).
BalusC
1
A DeltaSpike dodatkowo ma ViewAccesscopediWindowScoped
Kukeltje
@BalusC, myślę, że jest problem z ViewScopedfasolą w MyFaces 2.2. Obecnie mam do czynienia z problemem związanym z ViewScopedfasolą i Ajaxem, który opublikowałem tutaj . W MyFaces JIRA jest również dyskusja na ten temat.
Tapas Bose
CDI definiuje cztery wbudowane zakresy: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped dlaczego opisywane zakresy są różne?
Hosein Aqajani
122

Od wersji JSF 2.3 wszystkie zakresy komponentu bean zdefiniowane w pakiecie javax.faces.beanpakietów są przestarzałe, aby wyrównać zakresy z CDI. Ponadto mają one zastosowanie tylko wtedy, gdy fasola używa @ManagedBeanadnotacji. Jeśli używasz wersji JSF poniżej 2.3, przeczytaj starszą odpowiedź na końcu.


Od JSF 2.3 tutaj są zakresy, które mogą być używane na JSF Backing Beans:

1@javax.enterprise.context.ApplicationScoped .: Zakres aplikacji utrzymuje się przez cały czas trwania aplikacji internetowej. Ten zakres jest wspólny dla wszystkich żądań i wszystkich sesji. Jest to przydatne, gdy masz dane dla całej aplikacji.

2@javax.enterprise.context.SessionScoped .: Zakres sesji utrzymuje się od momentu ustanowienia sesji do jej zakończenia. Kontekst sesji jest wspólny dla wszystkich żądań występujących w tej samej sesji HTTP. Jest to przydatne, gdy nie chcesz zapisywać danych dla konkretnego klienta dla określonej sesji.

3@javax.enterprise.context.ConversationScoped .: Zakres konwersacji trwa tak długo, jak żyje fasola. Zakres obejmuje 2 metody: Conversation.begin()i Conversation.end(). Metody te powinny być jawnie wywoływane, aby rozpocząć lub zakończyć życie fasoli.

4@javax.enterprise.context.RequestScoped .: Zakres żądania jest krótkotrwały. Rozpoczyna się po przesłaniu żądania HTTP i kończy po odesłaniu odpowiedzi do klienta. Jeśli umieścisz zarządzaną fasolę w zakresie żądania, dla każdego żądania tworzona jest nowa instancja. Warto zastanowić się nad zakresem zapytania, jeśli obawiasz się kosztów przechowywania zakresu sesji.

5@javax.faces.flow.FlowScoped .: Zakres Flow utrzymuje się tak długo, jak trwa Flow. Przepływ może być zdefiniowany jako zawarty zestaw stron (lub widoków), które definiują jednostkę pracy. Zasięg działania Flow jest aktywny tak długo, jak użytkownik porusza się po nim w Flow.

6@javax.faces.view.ViewScoped .: Zasięg widoku komponentu bean utrzymuje się podczas ponownego wyświetlania tej samej strony JSF. Gdy tylko użytkownik przejdzie do innej strony, komponent bean wychodzi poza zakres.


Poniższa starsza odpowiedź dotyczy wersji JSF wcześniejszej niż 2.3

Od wersji JSF 2.x dostępne są 4 zakresy fasoli:

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

Zakres sesji: Zakres sesji utrzymuje się od momentu ustanowienia sesji do jej zakończenia. Sesja kończy się, jeśli aplikacja sieci Web wywoła metodę unieważnienia obiektu HttpSession lub przekroczy limit czasu.

RequestScope: Zakres żądania jest krótkotrwały. Rozpoczyna się po przesłaniu żądania HTTP i kończy po odesłaniu odpowiedzi do klienta. Jeśli umieścisz zarządzaną fasolę w zakresie żądania, dla każdego żądania tworzona jest nowa instancja. Warto zastanowić się nad zakresem zapytania, jeśli obawiasz się kosztów przechowywania zakresu sesji.

ApplicationScope: Zakres aplikacji utrzymuje się przez cały czas trwania aplikacji internetowej. Ten zakres jest wspólny dla wszystkich żądań i wszystkich sesji. Umieszczasz zarządzane fasole w zakresie aplikacji, jeśli jedna fasola powinna być współużytkowana przez wszystkie instancje aplikacji internetowej. Komponent bean jest konstruowany, gdy żąda go pierwszy użytkownik aplikacji, i pozostaje aktywny do momentu usunięcia aplikacji sieci web z serwera aplikacji.

ViewScope: Dodano zakres widoku w JSF 2.0. Zasięg widoku komponentu bean utrzymuje się podczas ponownego wyświetlania tej samej strony JSF. (Specyfikacja JSF używa terminu widok strony JSF.) Gdy tylko użytkownik przejdzie do innej strony, komponent bean wykracza poza zakres.

Wybierz zakres w oparciu o swoje wymagania.

Źródło: Core Java Server Faces 3. wydanie autorstwa David Geary & Cay Horstmann [Nr strony 51–54] wprowadź opis zdjęcia tutaj

Kishor Prakash
źródło
Czy możesz wyjaśnić, co rozumiesz przez „metodę unieważnienia obiektu HttpSession”: invalidate()metodę, czy metodę niepoprawną?
Alexander Pozdneev
1
Trochę stary i może spóźniony na odpowiedź, ale aby to wyjaśnić: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();bycie przywołanym w „fasoli wylogowania” jest tym, co ma na myśli.
Roland,
1
stało się starszą odpowiedzią, w tej chwili jest 8 zakresów
Ewoks
@KishorPrakash: jakiś czas jest teraz 6 miesięcy temu. ;-)
Kukeltje
@Kukeltje: Przepraszam, jestem na to.
Kishor Prakash