ServletContext
Lorsque le conteneur de servlets (comme Apache Tomcat ) démarre, il déploiera et chargera toutes ses applications Web. Lorsqu'une application Web est chargée, le conteneur de servlet crée ServletContext
une fois et la conserve dans la mémoire du serveur. L'application Web web.xml
et tous les web-fragment.xml
fichiers inclus sont analysés, et chacun <servlet>
, <filter>
et <listener>
trouvé (ou chaque classe annotée avec @WebServlet
, @WebFilter
et @WebListener
respectivement) est instancié une fois et également conservé dans la mémoire du serveur. Pour chaque filtre instancié, sa init()
méthode est invoquée avec un nouveau FilterConfig
.
Lorsque a Servlet
a une valeur <servlet><load-on-startup>
ou @WebServlet(loadOnStartup)
supérieure à 0
, sa init()
méthode est également invoquée lors du démarrage avec un nouveau ServletConfig
. Ces servlets sont initialisés dans le même ordre spécifié par cette valeur ( 1
est le 1er, le 2
2e, etc.). Si la même valeur est spécifiée pour plus d'un servlet, alors chacun de ces servlets est chargé dans le même ordre que dans le web.xml
, web-fragment.xml
ou @WebServlet
classloading. Dans le cas où la valeur "load-on-startup" est absente, la init()
méthode sera invoquée chaque fois que la requête HTTP atteindra ce servlet pour la toute première fois.
Lorsque le conteneur de servlet a terminé toutes les étapes d'initialisation décrites ci-dessus, alors le ServletContextListener#contextInitialized()
sera invoqué.
Lorsque le conteneur se ferme de servlet vers le bas, il décharge toutes les applications Web, appelle la destroy()
méthode de tous ses servlets et les filtres initialisées, et tous ServletContext
, Servlet
, Filter
et les Listener
cas sont saccagés. Enfin, le ServletContextListener#contextDestroyed()
sera invoqué.
HttpServletRequest et HttpServletResponse
Le conteneur de servlet est attaché à un serveur Web qui écoute les requêtes HTTP sur un certain numéro de port (le port 8080 est généralement utilisé pendant le développement et le port 80 en production). Lorsqu'un client (utilisateur , par exemple avec un navigateur Web ou par programmationURLConnection
) envoie une requête HTTP, le conteneur de servlet crée de nouveaux HttpServletRequest
et des HttpServletResponse
objets et les passe par une définition Filter
de la chaîne et, éventuellement, l' Servlet
instance.
Dans le cas des filtres , la doFilter()
méthode est invoquée. Lorsque le code du conteneur de servlet appelle chain.doFilter(request, response)
, la demande et la réponse continuent au filtre suivant, ou appuyez sur la servlet s'il n'y a plus de filtre.
Dans le cas des servlets , la service()
méthode est invoquée. Par défaut, cette méthode détermine la doXxx()
méthode à invoquer en fonction de laquelle request.getMethod()
. Si la méthode déterminée est absente du servlet, une erreur HTTP 405 est renvoyée dans la réponse.
L'objet de demande donne accès à toutes les informations sur la demande HTTP, telles que son URL, ses en-têtes, sa chaîne de requête et son corps. L'objet de réponse permet de contrôler et d'envoyer la réponse HTTP comme vous le souhaitez, par exemple, en vous permettant de définir les en-têtes et le corps (généralement avec du contenu HTML généré à partir d'un fichier JSP). Lorsque la réponse HTTP est validée et terminée, les objets de demande et de réponse sont recyclés et mis à disposition pour être réutilisés.
HttpSession
Lorsqu'un client visite la webapp pour la première fois et / ou HttpSession
est obtenu pour la première fois via request.getSession()
, le conteneur de servlet crée un nouvel HttpSession
objet, génère un ID long et unique (que vous pouvez obtenir session.getId()
) et le stocke dans le serveur Mémoire. Le conteneur de servlet définit également un Cookie
dans l'en- Set-Cookie
tête de la réponse HTTP avec JSESSIONID
comme nom et l'ID de session unique comme valeur.
Conformément à la spécification de cookie HTTP (un contrat auquel tout navigateur Web et serveur Web décent doit adhérer), le client (le navigateur Web) est tenu de renvoyer ce cookie dans les demandes suivantes dans l'en- Cookie
tête tant que le cookie est valide ( c'est-à-dire que l'ID unique doit faire référence à une session non expirée et que le domaine et le chemin sont corrects). En utilisant le moniteur de trafic HTTP intégré de votre navigateur, vous pouvez vérifier que le cookie est valide (appuyez sur F12 dans Chrome / Firefox 23+ / IE9 +, et vérifiez l' onglet Net / Réseau ). Le conteneur de servlet vérifiera l'en- Cookie
tête de chaque requête HTTP entrante pour la présence du cookie avec le nom JSESSIONID
et utilisera sa valeur (l'ID de session) pour obtenir l'associé HttpSession
de la mémoire du serveur.
Le HttpSession
reste en vie jusqu'à ce qu'il soit inactif (c'est-à-dire non utilisé dans une demande) pendant plus que la valeur de temporisation spécifiée dans <session-timeout>
, un paramètre dans web.xml
. La valeur du délai d'attente est par défaut de 30 minutes. Ainsi, lorsque le client ne visite pas l'application Web plus longtemps que la durée spécifiée, le conteneur de servlet met la session au rebut. Chaque demande ultérieure, même avec le cookie spécifié, n'aura plus accès à la même session; le conteneur de servlet créera une nouvelle session.
Côté client, le cookie de session reste actif aussi longtemps que l'instance de navigateur est en cours d'exécution. Ainsi, si le client ferme l'instance de navigateur (tous les onglets / fenêtres), la session est mise à la poubelle du côté du client. Dans une nouvelle instance de navigateur, le cookie associé à la session n'existerait pas, il ne serait donc plus envoyé. Cela entraîne la HttpSession
création d'un tout nouveau, avec un cookie de session entièrement nouveau utilisé.
En un mot
- La
ServletContext
vie aussi longtemps que dure l'application Web. Il est partagé entre toutes les demandes de toutes les sessions.
- La
HttpSession
vie dure aussi longtemps que le client interagit avec l'application Web avec la même instance de navigateur et que la session n'a pas expiré côté serveur. Il est partagé entre toutes les demandes d'une même session.
- Le
HttpServletRequest
et en HttpServletResponse
direct à partir du moment où le servlet reçoit une demande HTTP du client, jusqu'à ce que la réponse complète (la page Web) soit arrivée. Il n'est pas partagé ailleurs.
- Tous
Servlet
, Filter
et les Listener
instances vivent aussi longtemps que l'application Web vit. Ils sont partagés entre toutes les demandes dans toutes les sessions.
- Tout
attribute
qui est défini dans ServletContext
, HttpServletRequest
et HttpSession
vivra aussi longtemps que l'objet dans la vie de question. L'objet lui-même représente la «portée» dans les cadres de gestion de bean tels que JSF, CDI, Spring, etc. Ces cadres stockent leurs beans étendus en tant que attribute
sa portée de correspondance la plus proche.
Sécurité des fils
Cela dit, votre principale préoccupation est peut-être la sécurité des threads . Vous devez maintenant savoir que les servlets et les filtres sont partagés entre toutes les demandes. C'est la bonne chose à propos de Java, il est multithread et différents threads (lire: requêtes HTTP) peuvent utiliser la même instance. Il serait autrement trop cher à recréer, init()
et destroy()
eux pour chaque demande.
Vous devez également comprendre que vous ne devez jamais affecter de données de portée de demande ou de session en tant que variable d' instance d'un servlet ou d'un filtre. Il sera partagé entre toutes les autres demandes des autres sessions. Ce n'est pas thread-safe! L'exemple ci-dessous illustre ceci:
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.
}
}
Voir également: