Dlaczego JSF musi zapisywać stan komponentów UI po stronie serwera?
Ponieważ protokół HTTP jest bezstanowy, a JSF jest stanowy. Drzewo komponentów JSF podlega dynamicznym (programowym) zmianom. JSF musi po prostu znać dokładny stan, w jakim był, kiedy formularz został wyświetlony użytkownikowi końcowemu, aby mógł z powodzeniem przetworzyć cały cykl życia JSF w oparciu o informacje dostarczone przez oryginalne drzewo komponentów JSF, gdy formularz został przesłany z powrotem do serwer. Drzewo komponentów zawiera informacje o nazwach parametrów żądania, niezbędnych konwerterach / walidatorach, powiązanych właściwościach zarządzanego komponentu bean i metodach akcji.
Do jakiego momentu JSF zapisuje stan komponentów UI po stronie serwera i kiedy dokładnie informacje o stanie komponentu UI są usuwane z pamięci serwera?
Te dwa pytania wydają się sprowadzać do tego samego. W każdym razie jest to specyficzne dla implementacji, a także zależne od tego, czy stan jest zapisany na serwerze czy kliencie. Nieco przyzwoita implementacja usunie ją, gdy wygasła lub gdy kolejka jest pełna. Na przykład Mojarra ma domyślny limit 15 widoków logicznych, gdy zapisywanie stanu jest ustawione na sesję. Można to skonfigurować za pomocą następującego parametru kontekstu w web.xml
:
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>15</param-value>
</context-param>
Zobacz także Mojarra FAQ dla innych parametrów specyficznych dla Mojarra i tę powiązaną odpowiedź com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
Kiedy zalogowany użytkownik aplikacji nawiguje po stronach, czy stan komponentów będzie się gromadził na serwerze?
Technicznie zależy to od implementacji. Jeśli mówisz o nawigacji między stronami (tylko żądania GET), Mojarra nie zapisuje niczego w sesji. Jeśli są to jednak żądania POST (formularze z linkami poleceń / przyciskami), Mojarra zapisze stan każdego formularza w sesji do maksymalnego limitu. Umożliwia to użytkownikowi końcowemu otwieranie wielu formularzy na różnych kartach przeglądarki w tej samej sesji.
Lub, gdy zapisywanie stanu jest ustawione na klienta, JSF nie przechowuje niczego w sesji. Możesz to zrobić za pomocą następującego parametru kontekstu w web.xml
:
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Następnie zostanie on serializowany do zaszyfrowanego ciągu w ukrytym polu wejściowym z nazwą javax.faces.ViewState
formularza.
Nie rozumiem, jakie są korzyści z utrzymywania stanu składnika interfejsu użytkownika po stronie serwera. Czy bezpośrednie przekazywanie zweryfikowanych / przekonwertowanych danych do zarządzanych komponentów bean nie jest wystarczające? Czy mogę / powinienem spróbować tego uniknąć?
To nie wystarczy, aby zapewnić integralność i solidność JSF. JSF to dynamiczna struktura z jednym punktem kontroli. Bez zarządzania państwem, jeden byłby w stanie naciąganie / Hack żądania HTTP w określony sposób (np manipulacyjny disabled
, readonly
a rendered
atrybuty), aby robić różne JSF-i potencjalnie hazardful- rzeczy. Byłby nawet podatny na ataki CSRF i phishing.
I czy nie zajmie to zbyt dużo pamięci po stronie serwera, jeśli są tysiące jednoczesnych sesji użytkowników? Mam aplikację, w której użytkownicy mogą publikować blogi na określone tematy. Te blogi są dość duże. Kiedy pojawi się wiadomość zwrotna lub prośba o przeglądanie blogów, duże blogi zostaną zapisane jako część stanu komponentów. Zajmowałoby to zbyt dużo pamięci. Czy to nie problem?
Pamięć jest szczególnie tania. Po prostu daj serwerowi aplikacji wystarczającą ilość pamięci. Lub jeśli przepustowość sieci jest dla Ciebie tańsza, po prostu przełącz zapisywanie stanu po stronie klienta. Aby znaleźć najlepsze dopasowanie, po prostu stresuj i sprofiluj swoją aplikację internetową z przewidywaną maksymalną liczbą jednoczesnych użytkowników, a następnie daj serwerowi aplikacji 125% ~ 150% maksymalnej zmierzonej pamięci.
Zwróć uwagę, że JSF 2.0 znacznie poprawiło zarządzanie stanem. Jest to możliwe, aby zapisać stan częściowego (np tylko<h:form>
zostaną zapisane zamiast całej rzeczy z <html>
całą drogę do końca). Na przykład Mojarra to robi. Przeciętny formularz z 10 polami wejściowymi (każde z etykietą i komunikatem) oraz 2 przyciskami zajmowałby nie więcej niż 1 KB. Przy 15 wyświetleniach w sesji nie powinno to być więcej niż 15 KB na sesję. Przy ~ 1000 jednoczesnych sesji użytkowników nie powinno to przekraczać 15 MB.
Twoje obawy powinny być bardziej skoncentrowane na rzeczywistych obiektach (zarządzanych komponentach bean i / lub nawet jednostkach bazy danych) w sesji lub zakresie aplikacji. Widziałem wiele kodów i projektów, które niepotrzebnie duplikują całą tabelę bazy danych do pamięci Javy w smaku fasoli o zasięgu sesji, gdzie zamiast języka SQL do filtrowania / grupowania / porządkowania rekordów używana jest Java. Przy ~ 1000 rekordów z łatwością przekroczyłoby to 10 MB na sesję użytkownika .