Comment fonctionnent les servlets? Instanciation, sessions, variables partagées et multithreading
supposons que j'ai un serveur web qui contient de nombreux servlets. Pour les informations qui passent parmi ces servlets, je mets en place des variables de session et d'instance.
maintenant, si 2 utilisateurs ou plus envoient une requête à ce serveur, qu'arrive-t-il aux variables de session? Seront-ils tous être commun à tous les utilisateurs ou ils seront différents pour chaque utilisateur. S'ils sont différents, comment le serveur a-t-il pu faire la différence entre les différents utilisateurs?
One question plus similaire, s'il y a des utilisateurs n
qui accèdent à un servlet particulier, alors ce servlet n'est instancié que la première fois que le premier utilisateur y accède ou est-il instancié pour tous les utilisateurs séparément? En d'autres termes, qu'arrive-t-il aux variables d'instance?
7 réponses
ServletContext
lorsque le conteneur servlet (comme Apache Tomcat ) démarre, il déploiera et chargera toutes ses applications web. Lorsqu'une application web est chargée, le conteneur servlet crée le ServletContext
une fois et le garde dans la mémoire du serveur. Le fichier web.xml
de l'application web est analysé, et chaque <servlet>
, <filter>
et <listener>
trouvé (ou chaque classe annotée avec @WebServlet
, @WebFilter
et @WebListener
, respectivement) est instancié une fois et conservé dans la mémoire du serveur. Pour chaque filtre instancié, sa méthode init()
est invoquée avec un nouveau FilterConfig
.
lorsque le conteneur servlet s'éteint, il décharge toutes les applications web, invoque la méthode destroy()
de tous ses servlets et filtres initialisés, et tous ServletContext
, Servlet
, Filter
et Listener
instances sont trash.
Lorsqu'un Servlet
a une valeur <servlet><load-on-startup>
ou @WebServlet(loadOnStartup)
supérieure à 0
, sa méthode init()
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 -> 1er, 2 -> 2e, etc.). Si la même valeur est spécifiée pour plus d'une servlet, puis chacune de ces servlets est chargé dans l'ordre où ils apparaissent dans le web.xml
, ou @WebServlet
classloading. Dans le cas où la valeur" load-on-startup "est absente, la méthode init()
sera invoquée chaque fois que la requête HTTP atteint ce servlet pour la toute première fois.
HttpServletRequest et HttpServletResponse
le conteneur servlet est attaché à un serveur web qui écoute les requêtes HTTP sur un certain numéro de port (le port 8080 est habituellement utilisé pendant le développement et le port 80 en production). Lorsqu'un client (utilisateur avec un navigateur web) envoie une requête HTTP, le conteneur servlet crée de nouveaux HttpServletRequest
et HttpServletResponse
objets et les passe à travers toute chaîne définie Filter
et, éventuellement, l'instance Servlet
.
dans le cas de filtres , la méthode doFilter()
est invoquée. Lorsque son code appelle chain.doFilter(request, response)
, la requête et la réponse continuent sur le filtre suivant, ou frappent le servlet s'il n'y a pas de filtres restants.
dans le cas de servlets , la méthode service()
est invoquée. Par défaut, cette méthode détermine laquelle des méthodes doXxx()
à invoquer basée sur off de 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 request donne accès à toutes les informations relatives à la requête HTTP, comme ses têtes et son corps. L'objet response fournit la possibilité de contrôler et d'envoyer la réponse HTTP de la manière que vous voulez, 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 engagée et terminée, les objets request et response sont recyclés et réutilisés.
HttpSession
Lorsqu'un client visite le webapp pour la première fois et/ou le HttpSession
est obtenu pour la première fois via request.getSession()
, le conteneur servlet crée un nouvel objet 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 servlet définit également un Cookie
dans l'en-tête Set-Cookie
de la réponse HTTP avec JSESSIONID
comme nom et L'ID de session unique comme valeur.
selon le spécification de cookie HTTP (un contrat auquel un navigateur Web et un serveur web doivent adhérer), le client (le navigateur web) est requis de renvoyer ce cookie dans les requêtes suivantes dans l'en-tête Cookie
aussi longtemps que le cookie est valide (c.-à-d. L'ID unique doit se référer à une session non expirée et le domaine et le chemin sont corrects). En utilisant le 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 cochez l'onglet Net/Network ). Le conteneur servlet vérifiera l'en-tête Cookie
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 le HttpSession
associé à partir de la mémoire du serveur.
le HttpSession
reste vivant jusqu'à ce qu'il n'ait pas été utilisé pour plus de la valeur de temporisation spécifiée dans <session-timeout>
, un paramètre dans web.xml
. Le par défaut, la valeur de temporisation est de 30 minutes. Ainsi, lorsque le client ne visite pas l'application web plus longtemps que le temps spécifié, le conteneur servlet détruit la session. Chaque requête subséquente, même avec le cookie spécifié, n'aura plus accès à la même session; le conteneur servlet créera une nouvelle session.
côté client, le cookie de session reste actif aussi longtemps que l'instance du navigateur est active. Donc, si le client ferme l'instance du navigateur (tous tabs / windows), puis la session est saccagée du côté du client. Dans le cas d'un nouveau navigateur, le cookie associé à la session n'existerait pas et ne serait donc plus envoyé. Cela entraîne la création d'un tout nouveau HTTPSession
, avec un cookie de session begin utilisé entièrement nouveau.
en un mot
- Le
ServletContext
vies aussi longtemps que l'application web vie. Elle est partagée entre toutes les requêtes en toutes sessions. - le
HttpSession
vit aussi longtemps que le client interagit avec l'application web avec la même instance de navigateur, et la session n'a pas chronométré du côté du serveur. Il est partagé entre toutes les requêtes dans la même session. - Le
HttpServletRequest
etHttpServletResponse
en direct de la servlet reçoit une requête HTTP du client, jusqu'à ce que la réponse complète (la page web) est arrivé. Elle est et non partagée ailleurs. - Tous
Servlet
,Filter
etListener
les instances de vivre aussi longtemps que l'application web vie. Ils sont partagés entre toutes demandes dans toutes sessions. - toute
attribute
qui est définie dansServletContext
,HttpServletRequest
etHttpSession
vivra aussi longtemps que l'objet en question la vie. L'objet lui-même représente la "portée" dans les cadres de gestion des bean tels que JSF, CDI, Spring, etc. Ces cadres stockent leurs haricots scoped comme unattribute
de son plus proche correspondant portée.
Filet De Sécurité
cela dit, votre principale préoccupation est peut-être sécurité des fils . Vous devez maintenant savoir que les servlets et les filtres sont partagés entre toutes les demandes. C'est la chose gentille de Java, c'est multithreaded et différents threads (read: requêtes HTTP) peuvent utiliser la même instance. Il serait trop coûteux de recréer, init()
et destroy()
pour chaque requête unique.
vous devriez également vous rendre compte que vous devriez jamais assigner n'importe quelle demande ou session scoped des données comme une instance variable d'un servlet ou d'un filtre. Il sera partagé entre toutes les autres demandes session. C'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 aussi:
- Quelle est la différence entre JSF, Servlet et JSP?
- meilleure option pour la gestion de Session en Java
- la Différence entre / et /* dans le servlet de cartographie de modèle d'url
- doGet et doPost dans les Servlets
- Servlet semble gérer simultanément plusieurs requêtes du navigateur de façon synchrone
- pourquoi les Servlets ne sont pas sécuritaires?
Sessions
en bref: le serveur web émet un identifiant unique à chaque visiteur lors de sa première visite. Le visiteur doit rapporter cette pièce D'identité pour être reconnu la prochaine fois. Cet identifiant permet également au serveur de bien séparer les objets appartenant à une session par rapport à ceux appartenant à une autre.
Servlet Instantiation
Si load-on-startup est false :
Si load-on-startup est vrai :
une fois qu'il est en mode service et sur la rainure, le même servlet va travailler sur les demandes de tous les autres clients.
pourquoi n'est-ce pas une bonne idée d'avoir une instance par client? Pensez à ceci: allez-vous engager un livreur de pizza pour chaque commande qui est arrivée? Le faire et vous serez hors de l'entreprise en un rien de temps.
Il est livré avec un petit risque. Rappelez-vous: ce gars célibataire détient toutes les informations de l'ordre dans sa poche: alors si vous n'êtes pas prudent au sujet de sécurité de fil sur servlets , il peut finir par donner la mauvaise commande à un certain client.
Session en Java servlets est la même que session dans D'autres langues telles que PHP. Il est unique pour l'utilisateur. Le serveur peut garder la trace de différentes façons telles que les cookies, la réécriture d'url, etc. Cet article Java doc l'explique dans le contexte des servlets Java et indique que la façon exacte dont la session est maintenue est un détail d'implémentation laissé aux concepteurs du serveur. La spécification prévoit seulement qu'elle doit être maintenue propre à un utilisateur à travers plusieurs connexions au serveur. Consultez cet article de Oracle pour plus d'informations sur vos deux questions.
Modifier Il y a un excellent tutoriel ici sur la façon de travailler avec la session à l'intérieur de servlets. Et ici est un chapitre de Sun sur les Servlets Java, ce qu'ils sont et comment les utiliser. Entre ces deux articles, vous devriez pouvoir répondre à toutes vos questions.
quand le servletcontainer (comme Apache Tomcat) démarre, il lit sur le web.fichier xml (un seul par application) si quelque chose tourne mal ou affiche une erreur à la console côté conteneur, sinon il déploiera et chargera toutes les applications Web en utilisant web.xml (donc nommé comme descripteur de déploiement).
pendant la phase d'instanciation de servlet, servlet est prêt mais il ne peut pas répondre à la demande du client car il manque deux informations:
1: Information sur le contexte
2: informations de configuration initiale
moteur de Servlet crée servletConfig interface de l'objet au-dessus de l'encapsulation de l'information manquante dans il servlet engine appelle INIT () of servlet en suplying servletConfig object references as argument. Une fois que init() est entièrement exécuté, servlet est prêt à server la requête client.
Q) dans le temps de vie de servlet combien de fois l'instanciation et l'initaialization qui se passe ??
a)une seule fois (pour chaque requête client un nouveau thread est créé) une seule instance du servlet sert n'importe quel nombre de la requête client, c'est-à-dire qu'après avoir servi un serveur de requête client ne meurt pas. Il attend les demandes d'autres clients c'est-à-dire ce que CGI (pour chaque demande d'un client, un nouveau processus est créé) la limitation est surmontée avec servlet (moteur de servlet interne crée du thread).
Q)comment le concept de session œuvres?
a) chaque fois que getSession() est appelé sur L'objet HttpServletRequest
Step 1 : l'objet request est évalué pour l'ID de session entrant.
Step 2 : si L'ID n'est pas disponible, un nouvel objet HttpSession est créé et l'ID de session correspondant est généré (c'est-à-dire le HashTable) L'ID de session est stocké dans l'objet de réponse httpservlet et la référence de L'objet HttpSession est retour à servlet (doGet / doPost).
Step 3 : si ID disponible tout nouvel objet de session n'est pas créé, L'ID de session est récupéré à partir de la requête la recherche d'objet est effectuée dans la collection de sessions en utilisant l'ID de session comme clé.
une fois que la recherche est réussie, l'ID de session est stocké dans HttpServletResponse et les références d'objet de session existantes sont retournées dans doGet() ou doPost() de Userdefineeservlet.
Note:
1) lorsque le contrôle quitte le code servlet pour le client, n'oubliez pas que l'objet session est tenu par servletcontainer ie, servletengine
2)le multithreading est la gauche vers la servlet devlopers personnes pour la mise en œuvre de ie., gérer la demande multiple du client rien à se soucier de code multithread
forme abrégée:
un servlet est créé lorsque l'application démarre (il est déployé sur le container servlet) ou quand il est accédé pour la première fois (selon le réglage de la charge au démarrage)) lorsque la servlet est instancié, la méthode init() de la servlet est appelé puis le servlet (sa seule et unique instance) gère toutes les requêtes (sa méthode service () étant appelée par plusieurs threads). C'est pourquoi il n'est pas conseillé d'y avoir une synchronisation, et vous devriez éviter les variables d'instance du servlet lorsque l'application n'est pas déployée (le conteneur servlet arrêts), le détruire() la méthode est appelée.
Sessions - ce que Chris Thompson a dit.
Instantiation - un servlet est instancié lorsque le conteneur reçoit la première requête mappée sur le servlet (à moins que le servlet ne soit configuré pour charger au démarrage avec l'élément <load-on-startup>
dans web.xml
). La même instance est utilisée pour servir des requêtes ultérieures.
La Spécification Servlet JSR-315 définit clairement le conteneur web de comportement dans le service (et doGet, doPost, le doput etc.) méthodes (2.3.3.1 questions en plusieurs lectures, Page 9):
un conteneur servlet peut envoyer des requêtes concurrentes à travers le service méthode de la servlet. Pour traiter les requêtes, le développeur Servlet doit prévoir des dispositions adéquates pour le traitement simultané avec plusieurs les threads dans le service méthode.
bien qu'il ne soit pas recommandé, une alternative pour le développeur est de implémenter L'interface SingleThreadModel qui nécessite le conteneur afin de garantir qu'il existe une seule demande thread à la fois dans le méthode de service. Un réservoir de service peut satisfaire à cette exigence en: sérialiser les requêtes sur un servlet, ou en maintenant un pool de servlet instance. Si le servlet fait partie d'une application Web qui a été marqué comme distribuable, l' le contenant peut contenir une réserve de exemples dans chaque JVM où la demande est distribuée.
pour les servlets ne mettant pas en œuvre L'interface SingleThreadModel, si le méthode de service (ou méthodes telles que doGet ou doPost qui sont envoyé à la méthode de service de la classe abstract HttpServlet) a été défini avec le mot-clé synchronisé, le conteneur servlet ne peut pas utiliser l'approche de pool d'instances, mais doit sérialiser les requêtes à travers elle. Il est fortement recommandé aux Développeurs de ne pas synchroniser la méthode de service (méthodes ou distribué) dans ces circonstances dues à des effets préjudiciables sur l'exécution
nous pouvons faire méthode de service entier comme synchronisé en utilisant synchronisé
keword devant la méthode
exemple::
public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException
ou nous pouvons mettre le bloc du code dans le bloc synchronisé
exemple::
Synchronized(Object)
{
----Instructions-----
}
j'ai l'impression que Synchronisés bloc est mieux que de faire toute la méthode
synchronisé