Question Comment fonctionnent les servlets? Instanciation, sessions, variables partagées et multithreading


Supposons que j'ai un serveur web qui contient de nombreuses servlets. Pour l'information passant parmi ces servlets je mets des variables de session et d'instance.

Maintenant, si 2 utilisateurs ou plus envoient une requête à ce serveur, qu'advient-il des variables de session? Seront-ils tous communs pour tous les utilisateurs ou ils seront différents pour chaque utilisateur. Si elles sont différentes, comment le serveur peut-il différencier les différents utilisateurs?

Une autre question similaire, s'il y a n les utilisateurs accédant à une servlet particulière, alors cette servlet est instanciée seulement la première fois que le premier utilisateur y a accédé ou est-elle instanciée pour tous les utilisateurs séparément? En d'autres termes, qu'advient-il des variables d'instance?


989
2018-06-24 00:16


origine


Réponses:


ServletContext

Lorsque le conteneur de servlet (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 servlet crée le ServletContext une fois et le garde dans la mémoire du serveur. L'application web web.xml le fichier 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é, son init() méthode est appelée avec une nouvelle FilterConfig.

Lorsque le conteneur de servlet s'arrête, il décharge toutes les applications Web, appelle le destroy() méthode de tous ses servlets et filtres initialisés, et tous ServletContext, Servlet, Filter et Listener les instances sont saccagées.

Lorsqu'un Servlet a un <servlet><load-on-startup> ou @WebServlet(loadOnStartup) valeur supérieure à 0, son init() méthode est également appelée au démarrage avec un nouveau ServletConfig. Ces servlets sont initialisés dans le même ordre que celui spécifié par cette valeur (1 -> 1st, 2 -> 2nd, 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 où elles apparaissent dans le web.xml, ou @WebServlet classloading. En cas d'absence de la valeur "load-on-startup", le init() La méthode sera invoquée chaque fois que la requête HTTP touche ce servlet pour la toute première fois.

HttpServletRequest et HttpServletResponse

Le conteneur de servlet est connecté à 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 avec un navigateur Web) envoie une requête HTTP, le conteneur de servlet crée une nouvelle HttpServletRequest et HttpServletResponse objets et les passe à travers tout défini Filter chaîne et, finalement, la Servlet exemple.

Dans le cas de filtres, la doFilter() La méthode est invoquée. Quand son code appelle chain.doFilter(request, response), la demande 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 service() La méthode est invoquée. Par défaut, cette méthode détermine lequel des doXxx() méthodes à invoquer en fonction de request.getMethod(). Si la méthode déterminée est absente de la servlet, une erreur HTTP 405 est renvoyée dans la réponse.

L'objet request donne accès à toutes les informations sur la requête HTTP, telles que ses en-têtes et son corps. L'objet de réponse offre la possibilité de contrôler et d'envoyer la réponse HTTP comme vous le souhaitez, en vous permettant par exemple de définir les en-têtes et le corps (généralement avec le contenu HTML généré à partir d'un fichier JSP). Lorsque la réponse HTTP est validée et terminée, les objets de requête et de réponse sont tous deux recyclés et créés 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 nouveau HttpSession objet, génère un identifiant long et unique (que vous pouvez obtenir par session.getId()), et le stocker dans la mémoire du serveur. Le conteneur de servlet définit également Cookie dans le Set-Cookie en-tête de la réponse HTTP avec JSESSIONID comme son nom et l'ID de session unique comme sa valeur.

Selon le Spécification des cookies HTTP (un contrat auquel un navigateur Web et un serveur Web convenables doivent adhérer), le client (le navigateur Web) est requis pour renvoyer ce témoin dans des demandes ultérieures dans le Cookie en-tête tant que le cookie est valide (c'est-à-dire que l'identifiant unique doit se référer à une session non expirée et que le domaine et le chemin sont corrects). À l'aide du moniteur de trafic HTTP intégré de votre navigateur, vous pouvez vérifier que le cookie est valide (appuyez sur la touche F12 dans Chrome / Firefox 23+ / IE9 +, puis cochez la case Net / Réseau languette). Le conteneur de servlet vérifiera Cookie en-tête de chaque requête HTTP entrante pour la présence du cookie avec le nom JSESSIONID et utiliser sa valeur (l'ID de session) pour obtenir le HttpSession de la mémoire du serveur.

le HttpSession reste actif jusqu'à ce qu'il n'ait pas été utilisé pendant plus longtemps que la valeur du délai spécifié <session-timeout>, un cadre dans web.xml. La valeur du délai par défaut est de 30 minutes. Ainsi, lorsque le client ne visite pas l'application Web plus longtemps que le délai spécifié, le conteneur de servlet supprime la session. Chaque requête suivante, même avec le cookie spécifié, n'aura plus accès à la même session; le conteneur de servlet va créer une nouvelle session.

Du côté client, le cookie de session reste actif tant 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 saccagée du côté du client. Dans une nouvelle instance de navigateur, le cookie associé à la session n'existe pas, il ne sera donc plus envoyé. Cela provoque un tout nouveau HTTPSession être créé, avec un cookie de session entièrement nouveau commencer utilisé.

En un mot

  • le ServletContext vit aussi longtemps que l'application web vit. Il est partagé entre tout demandes en tout sessions.
  • le HttpSession 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é du côté serveur. Il est partagé entre tout demandes dans le même session.
  • le HttpServletRequest et HttpServletResponse en direct à 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. C'est ne pas partagé ailleurs.
  • Tout Servlet, Filter et Listener Les instances vivent aussi longtemps que l'application web vit. Ils sont partagés entre tout demandes en tout sessions.
  • Tout attribute cela est défini dans ServletContext, HttpServletRequest et HttpSession vivra aussi longtemps que l'objet en question vit. L'objet lui-même représente la "portée" dans les frameworks de gestion de bean tels que JSF, CDI, Spring, etc. Ces frameworks stockent leurs beans de portée en tant que attribute de sa portée correspondante la plus proche.

Sécurité du filetage

Cela dit, votre principale préoccupation est peut-être sécurité du filetage. Vous devriez maintenant savoir que les servlets et les filtres sont partagés entre toutes les demandes. C'est la bonne chose de Java, c'est multithread et différents threads (lire: requêtes HTTP) peuvent utiliser la même instance. Il serait autrement trop cher de recréer, init() et destroy() eux pour chaque demande unique.

Vous devriez également réaliser que vous devriez jamais affecter une demande ou des données de portée de session en tant que exemple variable d'une servlet ou d'un filtre. Il sera partagé entre toutes les autres demandes dans d'autres sessions. C'est ne 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:


1623
2018-06-24 02:41



Sessions

enter image description here enter image description here

En bref: le serveur web émet un identifiant unique chaque visiteur sur son premier visite. Le visiteur doit ramener cette carte d'identité pour qu'il soit reconnu la prochaine fois. Cet identifiant permet également au serveur de séparer correctement les objets appartenant à une session par rapport à ceux d'une autre session.

Instanciation de servlet

Si chargement au démarrage est faux:

enter image description here enter image description here

Si chargement au démarrage est vrai:

enter image description here enter image description here

Une fois qu'il est en mode service et sur le groove, le même servlet travaillera sur les demandes de tous les autres clients.

enter image description here

Pourquoi n'est-ce pas une bonne idée d'avoir une instance par client? Pensez-y: allez-vous embaucher un type de pizza pour chaque commande qui est venu? Faites cela et vous serez hors de l'affaire en un rien de temps.

Il vient cependant avec un petit risque. Rappelez-vous: ce célibataire détient toutes les informations de commande dans sa poche: donc si vous n'êtes pas prudent sécurité des threads sur les servlets, il peut finir par donner le mauvais ordre à un certain client.


394
2017-07-06 16:38



La session dans les servlets Java est la même que la session dans d'autres langages tels que PHP. C'est unique à l'utilisateur. Le serveur peut garder une trace de celui-ci de différentes manières telles que les cookies, la réécriture d'URL, etc. Document Java article 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 stipule seulement qu'elle doit être maintenue unique pour un utilisateur sur plusieurs connexions au serveur. Check-out cet article d'Oracle pour plus d'informations sur vos deux questions.

modifier Il y a un excellent tutoriel ici sur comment travailler avec la session à l'intérieur des servlets. Et ici est un chapitre de Sun sur Java Servlets, ce qu'ils sont et comment les utiliser. Entre ces deux articles, vous devriez être capable de répondre à toutes vos questions.


40
2018-06-24 00:20



Lorsque le servletcontainer (comme Apache Tomcat) démarre, il lit à partir du fichier web.xml (un par application) si quelque chose ne va pas ou affiche une erreur sur la console côté conteneur, sinon il déploiera et chargera toutes les applications web en utilisant web .xml (ainsi nommé comme descripteur de déploiement).

Pendant la phase d'instanciation du servlet, servletInstance est prêt mais il ne peut pas servir la requête du client car il manque deux informations:
1: informations de contexte
2: informations de configuration initiale

Le moteur de servlet crée un objet d'interface servletConfig encapsulant les informations manquantes ci-dessus Le moteur de servlet appelle init () de la servlet en remplissant les références d'objet servletConfig comme argument. Une fois que init () est exécuté, servlet est prêt à server la requête client.

Q) Dans la durée de vie de la servlet, combien de fois l'instanciation et l'initialisation se produisent?

A) une seule fois (pour chaque demande de client un nouveau thread est créé) une seule instance de la servlet sert un nombre quelconque de la demande du client, c'est-à-dire qu'après avoir servi une requête client, le serveur ne meurt pas. Il attend d'autres demandes de client c'est-à-dire que CGI (pour chaque client demande la création d'un nouveau processus) la limitation est surmontée avec la servlet (le moteur de servlet interne crée le thread).

Q) Comment fonctionne le concept de session?

A) chaque fois que getSession () est appelée sur l'objet HttpServletRequest

Étape 1: l'objet de requête est évalué pour l'ID de session entrant.

Étape 2: si l'ID n'est pas disponible, un nouvel objet HttpSession est créé et son ID de session correspondant est généré (ie de HashTable) l'ID de session est stocké dans l'objet réponse httpservlet et la référence de l'objet HttpSession est renvoyée au servlet (doGet / doPost).

Étape 3: si l'ID d'un nouvel objet de session disponible 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 en tant que clé.

Une fois la recherche réussie, l'ID de session est stocké dans HttpServletResponse et les références d'objet de session existantes sont renvoyées à doGet () ou à doPost () de UserDefineservlet.

Remarque:

1) lorsque le contrôle quitte le code de servlet pour le client, n'oubliez pas que l'objet de session est en attente par servletcontainer ie, servletengine

2) multithreading est laissé à devlopers servlet personnes pour la mise en œuvre ie., Gérer la requête multiple du client rien à déranger à propos du code multithread

Forme d'abrégé:

Une servlet est créée lorsque l'application démarre (elle est déployée sur le conteneur de servlet) ou lors de son premier accès (en fonction du paramètre de chargement au démarrage) lorsque la servlet est instanciée, la méthode init () du servlet est appelée alors la 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 est dé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 de servlet s'arrête), la méthode destroy () est appelée.


30
2018-02-22 12:54



Sessions- Ce que Chris Thompson a dit.

Instanciation - une servlet est instanciée lorsque le conteneur reçoit la première requête mappée à la servlet (sauf si la servlet est configurée pour se charger au démarrage avec le <load-on-startup> élément dans web.xml). La même instance est utilisée pour répondre aux demandes suivantes.


20
2018-06-24 00:27



La spécification de servlet JSR-315 définit clairement le comportement du conteneur Web dans les méthodes de service (et doGet, doPost, doPut, etc.) (2.3.3.1 Multithreading, page 9):

Un conteneur de servlet peut envoyer des demandes simultanées via le service   méthode de la servlet. Pour gérer les demandes, le développeur de servlets   doit prendre des dispositions adéquates pour le traitement simultané avec plusieurs   threads dans la méthode de service.

Bien que cela ne soit pas recommandé, une alternative pour le développeur est de   implémenter l'interface SingleThreadModel qui nécessite le conteneur   pour garantir qu'il n'y a qu'un seul thread de demande à la fois dans le   méthode de service. Un conteneur de servlet peut satisfaire à cette exigence en   sérialisation des demandes sur une servlet ou en maintenant un pool de servlet   instances. Si le servlet fait partie d'une application Web qui a été   marqué comme distribuable, le conteneur peut gérer un pool de servlet   instances dans chaque machine virtuelle Java que l'application est répartie.

Pour les servlets qui n'implémentent pas l'interface SingleThreadModel, si   méthode de service (ou méthodes telles que doGet ou doPost qui sont   distribué à la méthode de service de la classe abstraite HttpServlet)   a été défini avec le mot-clé synchronized, le conteneur de servlet   ne peut pas utiliser l'approche du pool d'instances, mais doit sérialiser les requêtes   à travers. Il est fortement recommandé aux développeurs de ne pas synchroniser   la méthode de service (ou les méthodes qui lui sont expédiées) dans ces   circonstances en raison des effets préjudiciables sur la performance


13
2018-03-05 11:41



Non. Les servlets sont pas de filetage

L'est permet d'accéder à plus d'un thread à la fois

Si vous voulez le rendre Servlet comme Thread safe., U peut aller pour

Implement SingleThreadInterface(i)  qui est une interface vide il n'y a pas

méthodes

ou nous pouvons aller pour synchroniser les méthodes

nous pouvons faire la 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 de code dans le bloc synchronisé

Exemple::

Synchronized(Object)

{

----Instructions-----

}

Je pense que le bloc synchronisé est mieux que de faire toute la méthode

Synchronisé


0
2018-04-14 15:32