web-dev-qa-db-fra.com

Différence entre chaque instance de servlet et chaque thread de servlet dans les servlets?

Existe-t-il plusieurs instances de classe de servlet? Comme j'entends "chaque instance de servlet" Quelqu'un peut-il développer cela?

83
giri

Lorsque le conteneur Servlet démarre, il:

  1. lit web.xml;
  2. trouve les servlets déclarés dans le chemin de classe; et
  3. charge et instancie chaque servlet une seule fois .

En gros, comme ceci:

String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();
String servletClass = parseWebXmlAndRetrieveServletClass();
HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();
servlet.init();
servlets.put(urlPattern, servlet); // Similar to a map interface.

Ces servlets sont stockés en mémoire et réutilisés chaque fois que l'URL de la demande correspond au url-pattern Associé au servlet. Le conteneur de servlet exécute ensuite un code similaire à:

for (Entry<String, HttpServlet> entry : servlets.entrySet()) {
    String urlPattern = entry.getKey();
    HttpServlet servlet = entry.getValue();
    if (request.getRequestURL().matches(urlPattern)) {
        servlet.service(request, response);
        break;
    }
}

La GenericServlet#service() décide à son tour laquelle des doGet(), doPost(), etc. à invoquer en fonction de HttpServletRequest#getMethod() .

Vous voyez, le servletcontainer réutilise la même instance de servlet pour chaque requête. En d'autres termes: les servlets sont partagées entre chaque requête. C'est pourquoi il est extrêmement important d'écrire du code de servlet de la manière threadsafe - ce qui est en fait simple: il suffit de pas d'assigner des données de portée de requête ou de session en tant que variables d'instance de servlet , mais tout comme la méthode des variables locales. Par exemple.

public class MyServlet 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.
    } 
}
186
BalusC

Non, il n'y a qu'une seule instance de la servlet qui est réutilisée pour plusieurs demandes de plusieurs clients. Cela conduit à deux règles importantes:

  • n'utilisez pas de variables d'instance dans un servlet, sauf pour les valeurs à l'échelle de l'application, le plus souvent obtenues à partir des paramètres de contexte.
  • ne faites pas de méthodes synchronized dans une servlet

(il en va de même pour les filtres de servlet et jsps)

30
Bozho

Selon le Java Servlet Specification Version 3.0 (pp. 6-7), il y aura une instance par déclaration par JVM, sauf si le servlet implémente SingleThreadModel, auquel cas il peut y avoir plusieurs instances par JVM .

11
Samuel Edwin Ward

Bien qu’il existe déjà quelques bonnes réponses, aucune d’entre elles n’a parlé d’une application Web Java déployée dans un environnement distribué. Il s’agit d’un scénario pratique dans lequel plusieurs instances d’une seule servlet sont créées. dans un environnement distribué, vous disposez d'un cluster de machines pour gérer la demande et la demande peut être envoyée à n'importe laquelle de ces machines. Chacune de ces machines doit être capable de gérer la demande et, par conséquent, chaque machine doit avoir une instance de MyAwesomeServlet dans sa JVM.

Ainsi, la déclaration correcte serait qu'il n'y a qu'une seule instance par JVM pour chaque servlet, à moins qu'elle n'implémente SingleThreadModel.

SingleThreadModel dit en termes simples que vous ne devez avoir qu'un seul thread par instance de Servlet, donc en gros, vous devez créer une instance par requête à venir pour la gérer, ce qui tue fondamentalement tout le concept de traitement des requêtes de manière parallèle et n'est pas considéré comme une bonne pratique car la création et l'initialisation de l'objet servlet prennent du temps avant d'être prêtes à traiter la demande.

6
Saurabh Patil

Il ne peut pas y avoir plusieurs instances de classe de servlet. Même lorsqu'il existe une instance du servlet, il est capable de gérer plusieurs demandes. Il est donc sage de ne pas utiliser de variables de niveau classe.

5
fastcodejava

Pour ceux qui connaissent le vrai JavaScript (pas seulement une bibliothèque de celui-ci), les servlets peuvent être considérés comme objets de fonction. En tant qu'objets fonctionnels, leur tâche principale est de faire quelque chose , au lieu de de stocker des informations dans leurs coffres. Il n'est pas nécessaire d'instancier plus d'une instance de chaque objet fonctionnel, avec la même logique que les méthodes de classe Java sont partagées entre toutes les instances de cette classe.

4
lcn