ServletContext
All'avvio del contenitore servlet (come Apache Tomcat ), verrà distribuito e caricato tutte le sue applicazioni Web. Quando viene caricata un'applicazione Web, il contenitore servlet crea ServletContext
una volta e la mantiene nella memoria del server. La web app web.xml
e tutti inclusi web-fragment.xml
viene analizzato i file, e ciascuno <servlet>
, <filter>
e <listener>
hanno trovato (o ogni classe annotati con @WebServlet
, @WebFilter
e @WebListener
rispettivamente) viene istanziato una volta e mantenute in memoria del server pure. Per ogni filtro istanziato, il suo init()
metodo viene richiamato con un nuovo FilterConfig
.
Quando a Servlet
ha un valore <servlet><load-on-startup>
o @WebServlet(loadOnStartup)
maggiore di 0
, il suo init()
metodo viene anche richiamato durante l'avvio con un nuovo ServletConfig
. Tali servlet sono inizializzati nello stesso ordine specificato da quel valore ( 1
è il 1o, 2
è il 2o, ecc.). Se lo stesso valore è specificato per più di una servlet, allora ogni servlet viene caricato nello stesso ordine in cui appaiono nella web.xml
, web-fragment.xml
o @WebServlet
classloading. Nel caso in cui il valore "load-on-startup" sia assente, il init()
metodo verrà invocato ogni volta che la richiesta HTTP raggiunge quel servlet per la prima volta.
Al termine del contenitore servlet con tutte le fasi di inizializzazione sopra descritte, ServletContextListener#contextInitialized()
verrà richiamato.
Quando gli chiude servlet container verso il basso, esso scarica tutte le applicazioni web, invoca il destroy()
metodo per tutti i suoi servlet e filtri inizializzati, e tutti ServletContext
, Servlet
, Filter
e Listener
istanze vengono cestinati. Alla fine ServletContextListener#contextDestroyed()
verrà invocato.
HttpServletRequest e HttpServletResponse
Il contenitore servlet è collegato a un server Web che ascolta le richieste HTTP su un determinato numero di porta (la porta 8080 viene generalmente utilizzata durante lo sviluppo e la porta 80 in produzione). Quando un client (ad esempio, utente con un browser web, o di programmazione utilizzandoURLConnection
) invia una richiesta HTTP, il contenitore di servlet crea nuovi HttpServletRequest
e HttpServletResponse
oggetti e li passa attraverso qualsiasi definita Filter
della catena e, infine, l' Servlet
istanza.
Nel caso dei filtri , doFilter()
viene invocato il metodo. Quando il codice del contenitore servlet chiama chain.doFilter(request, response)
, la richiesta e la risposta continuano al filtro successivo oppure premere il servlet se non ci sono filtri rimanenti.
Nel caso dei servlet , service()
viene invocato il metodo. Per impostazione predefinita, questo metodo determina quale dei doXxx()
metodi da richiamare in base request.getMethod()
. Se il metodo determinato è assente dal servlet, viene restituito un errore HTTP 405 nella risposta.
L'oggetto richiesta fornisce l'accesso a tutte le informazioni sulla richiesta HTTP, come URL, intestazioni, stringa di query e corpo. L'oggetto response offre la possibilità di controllare e inviare la risposta HTTP nel modo desiderato, ad esempio, consentendo di impostare le intestazioni e il corpo (di solito con contenuto HTML generato da un file JSP). Una volta eseguito il commit e il completamento della risposta HTTP, gli oggetti richiesta e risposta vengono riciclati e resi disponibili per il riutilizzo.
HttpSession
Quando un client visita la webapp per la prima volta e / o HttpSession
viene ottenuto per la prima volta tramite request.getSession()
, il contenitore servlet crea un nuovo HttpSession
oggetto, genera un ID lungo e univoco (che è possibile ottenere session.getId()
) e lo memorizza nel server memoria. Il contenitore servlet imposta anche Cookie
a Set-Cookie
nell'intestazione della risposta HTTP con JSESSIONID
come nome e l'ID sessione univoco come valore.
Secondo la specifica del cookie HTTP (un contratto a cui devono aderire qualsiasi browser Web e server Web decente), il client (il browser Web) è tenuto a rispedire questo cookie nelle richieste successive Cookie
nell'intestazione fintanto che il cookie è valido ( cioè l'ID univoco deve fare riferimento a una sessione non scaduta e il dominio e il percorso sono corretti). Utilizzando il monitoraggio del traffico HTTP integrato nel browser, è possibile verificare che il cookie sia valido (premere F12 in Chrome / Firefox 23+ / IE9 + e controllare la scheda Rete / Rete ). Il contenitore servlet controllerà l' Cookie
intestazione di ogni richiesta HTTP in entrata per la presenza del cookie con il nome JSESSIONID
e utilizzerà il suo valore (l'ID sessione) per ottenere l'associato HttpSession
dalla memoria del server.
Le HttpSession
rimane attivo fino stato inattivo (cioè non utilizzato in una richiesta) per più del valore di timeout specificato <session-timeout>
, un'impostazione web.xml
. Il valore di timeout viene impostato automaticamente su 30 minuti. Pertanto, quando il client non visita l'app Web per un periodo di tempo superiore a quello specificato, il contenitore servlet trascina la sessione. Ogni richiesta successiva, anche con il cookie specificato, non avrà più accesso alla stessa sessione; il contenitore servlet creerà una nuova sessione.
Sul lato client, il cookie di sessione rimane attivo fino a quando l'istanza del browser è in esecuzione. Pertanto, se il client chiude l'istanza del browser (tutte le schede / finestre), la sessione viene spostata sul lato client. In una nuova istanza del browser, il cookie associato alla sessione non esisterebbe, quindi non verrebbe più inviato. Ciò provoca la HttpSession
creazione di un tutto nuovo, con l'utilizzo di un cookie di sessione completamente nuovo.
In poche parole
- La
ServletContext
vita finché dura l'app web. È condiviso tra tutte le richieste in tutte le sessioni.
- Le
HttpSession
vite per tutto il tempo come il client interagisce con il web app con la stessa istanza del browser, e la sessione non è scaduta al lato server. È condiviso tra tutte le richieste nella stessa sessione.
- L'
HttpServletRequest
e HttpServletResponse
diretta dal momento in cui la servlet riceve una richiesta HTTP da parte del cliente, fino a quando la risposta completa (la pagina web) è arrivato. E ' non è condivisa altrove.
- Tutti
Servlet
, Filter
e Listener
le istanze vivere fintanto che l'applicazione web vive. Sono condivisi tra tutte le richieste in tutte le sessioni.
- Qualsiasi
attribute
che è definita in ServletContext
, HttpServletRequest
e HttpSession
vivrà fino a quando l'oggetto in questione vite. L'oggetto stesso rappresenta lo "scopo" nei framework di gestione dei bean come JSF, CDI, Spring, ecc. Tali framework memorizzano i loro bean con scope come uno attribute
dei suoi scopi di corrispondenza più vicini.
Sicurezza del filo
Detto questo, la tua principale preoccupazione è probabilmente la sicurezza del thread . Ora dovresti sapere che servlet e filtri sono condivisi tra tutte le richieste. Questa è la cosa bella di Java, è multithread e diversi thread (leggi: richieste HTTP) possono usare la stessa istanza. Altrimenti sarebbe troppo costoso ricrearli init()
e destroy()
loro per ogni singola richiesta.
Dovresti anche capire che non dovresti mai assegnare alcuna richiesta o dati nell'ambito della sessione come variabile di istanza di un servlet o filtro. Sarà condiviso tra tutte le altre richieste in altre sessioni. Quello è non thread-safe! L'esempio seguente illustra questo:
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.
}
}
Guarda anche: