ServletContext
Kiedy kontener serwletu (jak Apache Tomcat ) uruchomi się, wdroży i załaduje wszystkie swoje aplikacje internetowe. Po załadowaniu aplikacji WWW kontener serwletu tworzy go ServletContext
raz i przechowuje w pamięci serwera. Aplikacja internetowa użytkownika web.xml
, a wszystkie zawarte web-fragment.xml
jest analizowany pliki, a każdy <servlet>
, <filter>
a <listener>
znalezione (lub każda klasa opatrzone @WebServlet
, @WebFilter
a @WebListener
odpowiednio) jest tworzony raz i przechowywane w pamięci serwera, jak również. Dla każdego filtrowanego instancji jego init()
metoda jest wywoływana z nowym FilterConfig
.
Kiedy a Servlet
ma wartość <servlet><load-on-startup>
lub @WebServlet(loadOnStartup)
większą niż 0
, wówczas jego init()
metoda jest również wywoływana podczas uruchamiania z nową ServletConfig
. Te serwlety są inicjowane w tej samej kolejności określonej przez tę wartość ( 1
1, 2
2 itd.). Jeśli ta sama wartość jest określona na więcej niż jednej serwletu, to każdy z tych serwletów jest umieszczony na tej samej kolejności, jak w web.xml
, web-fragment.xml
lub @WebServlet
classloading. W przypadku braku wartości „ładuj przy uruchomieniu” init()
metoda zostanie wywołana za każdym razem, gdy żądanie HTTP trafi do tego serwletu po raz pierwszy.
Kiedy kontener serwletu zostanie zakończony wszystkimi opisanymi powyżej krokami inicjalizacji, ServletContextListener#contextInitialized()
zostanie wywołany.
Kiedy zamykają kontener serwletów w dół, to rozładowuje wszystkie aplikacje internetowe, wywołuje destroy()
metodę wszystkich zainicjowanych serwletów i filtrów, a wszystko ServletContext
, Servlet
, Filter
a Listener
przypadki są zaśmiecone. W końcu ServletContextListener#contextDestroyed()
zostanie wywołany.
HttpServletRequest i HttpServletResponse
Kontener serwletu jest podłączony do serwera WWW, który nasłuchuje żądań HTTP na określonym numerze portu (port 8080 jest zwykle używany podczas programowania, a port 80 w produkcji). Gdy klient (np użytkownik z poziomu przeglądarki internetowej, lub programowo przy użyciuURLConnection
) wysyła żądanie HTTP, kontener serwletów tworzy nowy HttpServletRequest
i HttpServletResponse
obiektów i przekazuje je poprzez dowolny zdefiniowany Filter
w łańcuchu, a ostatecznie do Servlet
instancji.
W przypadku filtrów The doFilter()
metoda jest wywoływana. Gdy wywoływany jest kod kontenera serwletu chain.doFilter(request, response)
, żądanie i odpowiedź są kontynuowane do następnego filtru lub trafiają w serwlet, jeśli nie ma już pozostałych filtrów.
W przypadku serwletów The service()
metoda jest wywoływana. Domyślnie ta metoda określa, na podstawie której z doXxx()
metod należy wywołać request.getMethod()
. Jeśli określona metoda jest nieobecna w serwlecie, w odpowiedzi zwracany jest błąd HTTP 405.
Obiekt żądania zapewnia dostęp do wszystkich informacji o żądaniu HTTP, takich jak adres URL, nagłówki, ciąg zapytania i treść. Obiekt odpowiedzi umożliwia kontrolowanie i wysyłanie odpowiedzi HTTP tak, jak chcesz, na przykład, umożliwiając ustawienie nagłówków i treści (zwykle z wygenerowaną treścią HTML z pliku JSP). Po zatwierdzeniu i zakończeniu odpowiedzi HTTP obiekty żądania i odpowiedzi są ponownie przetwarzane i udostępniane do ponownego użycia.
HttpSession
Gdy klient odwiedza aplikację internetową po raz pierwszy i / lub HttpSession
jest uzyskiwany po raz pierwszy request.getSession()
, kontener serwletu tworzy nowy HttpSession
obiekt, generuje długi i unikalny identyfikator (który można uzyskać session.getId()
) i zapisuje go w serwerze pamięć. Kontener serwletu ustawia również Cookie
w Set-Cookie
nagłówku odpowiedzi HTTP JSESSIONID
jako nazwę i unikalny identyfikator sesji jako wartość.
Zgodnie ze specyfikacją plików cookie HTTP (umowa musi być przestrzegana przez każdą przyzwoitą przeglądarkę internetową i serwer), klient (przeglądarka internetowa) musi przesłać ten plik cookie z powrotem w kolejnych żądaniach w Cookie
nagłówku, dopóki plik cookie jest ważny ( tzn. unikalny identyfikator musi odnosić się do sesji, która nie wygasła, a domena i ścieżka są poprawne). Za pomocą wbudowanego monitora ruchu HTTP w przeglądarce możesz sprawdzić, czy plik cookie jest prawidłowy (naciśnij klawisz F12 w przeglądarce Chrome / Firefox 23+ / IE9 + i sprawdź kartę Sieć / Sieć ). Kontener serwletu sprawdzi Cookie
nagłówek każdego przychodzącego żądania HTTP pod kątem obecności pliku cookie z nazwą JSESSIONID
i użyje jego wartości (identyfikatora sesji), aby uzyskać powiązanie HttpSession
z pamięci serwera.
Że HttpSession
pozostaje przy życiu, dopóki nie zostanie bezczynności (nie używany w żądaniu) dłużej niż wartość limitu czasu określonego w <session-timeout>
, w otoczeniu web.xml
. Wartość limitu czasu domyślnie wynosi 30 minut. Tak więc, gdy klient nie odwiedza aplikacji internetowej dłużej niż określony czas, kontener serwletu niszczy sesję. Każde kolejne żądanie, nawet z określonym plikiem cookie, nie będzie już miało dostępu do tej samej sesji; kontener serwletu utworzy nową sesję.
Po stronie klienta plik cookie sesji pozostaje aktywny tak długo, jak długo działa instancja przeglądarki. Tak więc, jeśli klient zamknie instancję przeglądarki (wszystkie karty / okna), sesja zostanie zniszczona po stronie klienta. W nowej instancji przeglądarki plik cookie powiązany z sesją nie istniałby, więc nie byłby już wysyłany. Powoduje to HttpSession
utworzenie zupełnie nowego pliku cookie z sesją.
W skrócie
- Trwa
ServletContext
tak długo, jak długo trwa aplikacja internetowa. Jest dzielony między wszystkie żądania we wszystkich sesjach.
- Trwa
HttpSession
tak długo, jak długo klient wchodzi w interakcję z aplikacją internetową z tą samą instancją przeglądarki, a sesja nie przekroczyła limitu czasu po stronie serwera. Jest dzielony między wszystkie żądania w tej samej sesji.
HttpServletRequest
I HttpServletResponse
na żywo od czasu serwlet odbiera żądania HTTP od klienta, aż do całkowitej odpowiedzi (strona internetowa) przyjechał. To jest nie podzielił się gdzie indziej.
- Wszystko
Servlet
, Filter
oraz Listener
przypadki, żyć tak długo jak żyje to aplikacja internetowa. Są one dzielone między wszystkie żądania we wszystkich sesjach.
- Wszelkie
attribute
która jest zdefiniowana w ServletContext
, HttpServletRequest
i HttpSession
będą żyć tak długo, jak obiekt w życiu zapytania. Sam obiekt reprezentuje „zakres” w ramach zarządzania komponentami, takimi jak JSF, CDI, Spring itp. Te struktury przechowują swoje fasole o attribute
określonym zasięgu jako najbliższy pasujący zakres.
Bezpieczeństwo wątków
To powiedziawszy, twoim głównym problemem jest prawdopodobnie bezpieczeństwo wątków . Powinieneś teraz wiedzieć, że serwlety i filtry są wspólne dla wszystkich żądań. To miło, że Java jest wielowątkowa, a różne wątki (czytaj: żądania HTTP) mogą korzystać z tej samej instancji. Byłoby inaczej być zbyt drogie, aby odtworzyć, init()
i destroy()
je dla każdego wniosku.
Należy również zdawać sobie sprawę, że nigdy nie należy przypisywać żadnych danych o zasięgu żądania lub sesji jako zmiennej instancji serwletu lub filtru. Zostanie on udostępniony między wszystkimi innymi żądaniami w innych sesjach. To nie jest bezpieczne dla wątków! Poniższy przykład ilustruje to:
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
Zobacz też: