ServletContext
Lorsque le conteneur de servlets (comme Apache Tomcat ) démarre, il va déployer et charger toutes ses applications web. Lorsqu'une application Web est chargée, le conteneur de servlets crée l'attribut ServletContext
une fois et le conserve dans la mémoire du serveur. L'application web web.xml
et tout ce qui est inclus web-fragment.xml
est analysé, et chaque <servlet>
, <filter>
y <listener>
trouvé (ou chaque classe annotée avec @WebServlet
, @WebFilter
y @WebListener
respectivement) seront instanciés une fois et seront également conservés dans la mémoire du serveur, enregistrés via la propriété ServletContext
. Pour chaque filtre instancié, son init()
est invoquée avec une nouvelle FilterConfig
qui contient à son tour l'argument ServletContext
.
Lorsqu'un Servlet
a un <servlet><load-on-startup>
o @WebServlet(loadOnStartup)
valeur supérieure à 0
alors son init()
est également invoquée lors du démarrage avec une nouvelle méthode ServletConfig
qui contient à son tour l'argument ServletContext
. Ces servlets sont initialisés dans l'ordre spécifié par cette valeur ( 1
est le premier, 2
est 2ème, etc). Si la même valeur est spécifiée pour plus d'une servlet, chacune de ces servlets est chargée dans l'ordre dans lequel elle apparaît dans le fichier web.xml
, web-fragment.xml
ou @WebServlet
le chargement des classes. Dans le cas où la valeur "load-on-startup" est absente, la classe init()
sera invoquée chaque fois que la méthode Demande HTTP frappe ce servlet pour la toute première fois.
Lorsque le conteneur de servlets a terminé toutes les étapes d'initialisation décrites ci-dessus, alors la fonction ServletContextListener#contextInitialized()
sera invoqué avec un ServletContextEvent
qui contient à son tour l'argument ServletContext
. Cela donnera au développeur la possibilité d'enregistrer de façon programmatique une autre Servlet
, Filter
o Listener
.
Lorsque le conteneur de servlets s'arrête, il décharge toutes les applications Web, invoque la fonction de contrôle de l'accès à l'information de l'entreprise. destroy()
de toutes ses servlets et filtres initialisés, et toutes les méthodes Servlet
, Filter
y Listener
enregistrées par l'intermédiaire de la ServletContext
sont mis à la poubelle. Enfin, le ServletContextListener#contextDestroyed()
sera invoqué et le ServletContext
lui-même sera mis à la poubelle.
HttpServletRequest
y HttpServletResponse
Le conteneur de servlets est attaché à un serveur web qui écoute les demandes 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 (par exemple, un utilisateur avec un navigateur Web, ou de manière programmatique en utilisant URLConnection
) envoie une requête HTTP, le conteneur de servlets crée de nouvelles HttpServletRequest
y HttpServletResponse
et les fait passer par tout objet défini Filter
dans la chaîne et, finalement, le Servlet
instance.
Dans le cas de filtres El doFilter()
est invoquée. Lorsque le code du conteneur de servlet appelle chain.doFilter(request, response)
la demande et la réponse passent au filtre suivant, ou au servlet s'il n'y a plus de filtres.
Dans le cas de servlets El service()
est invoquée. Par défaut, cette méthode détermine quel est l'un des éléments suivants doXxx()
les méthodes à invoquer en fonction de request.getMethod()
. Si la méthode déterminée est absente de la servlet, alors une erreur HTTP 405 est renvoyée dans la réponse.
L'objet de requête permet d'accéder à toutes les informations relatives à la requête HTTP, comme son URL , en-têtes , chaîne de requête et le corps. L'objet response 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 requête et réponse sont recyclés et peuvent être réutilisés.
HttpSession
Lorsqu'un client visite la webapp pour la première fois et/ou la HttpSession
est obtenu pour la première fois via request.getSession()
le conteneur de servlets crée un nouveau HttpSession
génère un ID long et unique (que vous pouvez obtenir par session.getId()
), et le stocke dans la mémoire du serveur. Le conteneur de servlets définit également un Cookie
dans le Set-Cookie
de la réponse HTTP avec JSESSIONID
comme son nom et l'ID de session unique comme sa valeur.
Conformément à la Spécification des cookies HTTP (un contrat que tout navigateur web et serveur web décent doit respecter), le client (le navigateur web) est tenu d'envoyer cet cookie dans les demandes ultérieures dans le Cookie
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). À l'aide du moniteur de trafic HTTP intégré à votre navigateur, vous pouvez vérifier que le cookie est valide (appuyez sur F12 dans Chrome / Firefox 23+ / IE9+, et vérifiez l'en-tête Net/Network tab). Le conteneur de servlets vérifiera le Cookie
de chaque requête HTTP entrante pour la présence du cookie avec le nom JSESSIONID
et utiliser sa valeur (l'identifiant de la session) pour obtenir l'identifiant de l'utilisateur associé. HttpSession
de la mémoire du serveur.
El HttpSession
reste en vie jusqu'à ce qu'il soit inactif (c'est-à-dire qu'il n'ait pas été utilisé dans une requête) pendant une durée supérieure à la valeur de délai d'attente spécifiée dans le champ <session-timeout>
un cadre dans web.xml
. La valeur par défaut du délai d'attente est de 30 minutes. Ainsi, lorsque le client ne visite pas l'application Web pendant une période plus longue que celle spécifiée, le conteneur de servlets met à la poubelle l'application Web. session . Chaque demande ultérieure, même avec le cookie spécifié, n'aura plus accès à la même session ; le conteneur de servlets créera une nouvelle session.
Du côté client, le cookie de session reste actif aussi longtemps que l'instance du navigateur est en cours d'exécution. Ainsi, si le client ferme l'instance du navigateur (tous les onglets/fenêtres), la session est mise à la poubelle du côté du client. Dans une nouvelle instance du navigateur, le cookie associé à la session n'existe plus et n'est donc plus envoyé. Cela entraîne une toute nouvelle HttpSession
pour être créé, un cookie de session entièrement nouveau étant utilisé.
En bref
- El
ServletContext
vit aussi longtemps que l'application web vit. Elle est partagée entre tous demandes en tous sessions.
- El
HttpSession
vit tant que le client interagit avec l'application web avec la même instance de navigateur, et que la session n'a pas expiré du côté du serveur. Elle est partagée entre tous demandes dans le même session.
- El
HttpServletRequest
y HttpServletResponse
vivent à partir du moment où la servlet reçoit une requête HTTP du client, jusqu'à ce que la réponse complète (la page web) soit arrivée. Il s'agit no partagé ailleurs.
- Tous
Servlet
, Filter
y Listener
Les instances vivent aussi longtemps que l'application web. Elles sont partagées entre tous demandes en tous sessions.
- Tout
attribute
qui est défini dans ServletContext
, HttpServletRequest
y HttpSession
vivra aussi longtemps que l'objet en question vivra. L'objet lui-même représente la "portée" dans les cadres de gestion des haricots tels que JSF, CDI, Spring, etc. Ces frameworks stockent leurs beans scopés sous la forme d'un objet attribute
de sa portée la plus proche.
Sécurité du fil
Cela dit, votre principale préoccupation est peut-être sécurité du fil . Vous devriez maintenant savoir que les servlets et les filtres sont partagés entre toutes les requêtes. C'est l'avantage de Java : il est multithread et différents threads (lire : requêtes HTTP) peuvent utiliser la même instance. Sinon, il serait trop coûteux de la recréer, init()
y destroy()
pour chaque demande.
Vous devez également réaliser que vous devez nunca assigner toute donnée de demande ou de session en tant qu'un instance d'une servlet ou d'un filtre. Elle sera partagée entre toutes les autres requêtes des autres sessions. C'est no sans risque pour les fils ! L'exemple ci-dessous l'illustre :
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 aussi :