2010-02-02 13 views

Respuesta

177

Cuando el contenedor de servlets comienza, es:

  1. web.xml lee;
  2. encuentra los servlets declarados en el classpath; y
  3. cargas y ejemplifica cada Servlet solo una vez.

A grandes rasgos, la siguiente:

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

Esos servlets se almacenan en la memoria y volver a utilizar cada vez que la URL de solicitud coincide con el servlet asociado url-pattern. El contenedor de servlets luego ejecuta un código similar a:

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() a su vez decide cuál de las doGet(), doPost(), etc .. para invocar basa en HttpServletRequest#getMethod().

Verá, el servletcontainer reutiliza la misma instancia de servlet para cada solicitud. En otras palabras: los servlets se comparten entre cada solicitud. Es por eso que es extremadamente importante escribir el código del servlet de la manera segura, que en realidad es simple: simplemente haga no asigne datos de solicitud o de ámbito de sesión como variables de instancia de servlet, sino como variables locales de método. P.ej.

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. 
    } 
} 
+21

+1. Añadiré que si la misma clase de servlet se asigna a dos URL diferentes en web.xml, se crean dos instancias. Pero el principio general aún se cumple, una instancia sirve múltiples solicitudes. – Yoni

+1

@BalusC, solo pregunto, ¿hay alguna forma de acceder al conjunto de servlets iniciados desde la aplicación web? – shabunc

+1

¿La variable thisIsNOTThreadSafe en la clase se comparte con diferentes usuarios o solo se comparte en las diferentes páginas del mismo usuario? Lo que quiero decir es que si navego por esta página en mi computadora y la ejecutas en tu computadora, ¿compartimos el mismo espacio de thisIsNOTThreadSafe? Gracias. – overshadow

27

No, solo hay una instancia del servlet que se reutiliza para múltiples solicitudes de varios clientes. Esto lleva a dos reglas importantes:

  • No utilice variables de instancia en un servlet, excepto para valores de toda la aplicación, la mayoría de las veces obtenidos a partir de parámetros de contexto.
  • no hacen métodos synchronized en un servlet

(mismo ocurre con los filtros de servlets y JSP)

3

No puede haber múltiples instancias de la clase servlet. Incluso cuando hay una instancia del servlet, es capaz de manejar múltiples solicitudes. Por lo tanto, es aconsejable no usar variables de nivel de clase.

9

Según el Java Servlet Specification Version 3.0 (pp. 6-7), habrá una instancia por declaración por JVM, a menos que el servlet implementa SingleThreadModel en cuyo caso puede haber múltiples instancias por JVM.

+0

Especificación del servlet 3. (página 6-7) La sección 2.2.1 Nota sobre el modelo de subproceso único, dice "La interfaz SingleThreadModel está en desuso en esta versión de la especificación " – Reva

3

Para aquellos que conocen JavaScript real (no solo una biblioteca), los servlets se pueden ver como objetos de función . Como objetos funcionales, la tarea principal de ellos es para hacer algo, en lugar de para almacenar alguna información en sus cofres.No es necesario crear una instancia de más de una instancia de cada objeto funcional, con el mismo razonamiento de que los métodos de clase Java se comparten entre todas las instancias de esa clase.

3

Aunque ya hay algunas buenas respuestas, ninguna de ellas habló sobre una aplicación web Java implementada en un entorno distribuido. Este es un escenario práctico donde en realidad se crean múltiples instancias de un solo servlet. En un entorno distribuido, tiene un conjunto de máquinas para gestionar la solicitud y la solicitud puede dirigirse a cualquiera de estas máquinas. Cada una de estas máquinas debe ser capaz de manejar la solicitud y, por lo tanto, cada máquina debe tener una instancia de su MyAwesomeServlet en su JVM.

Por lo tanto, la afirmación correcta sería que solo hay una instancia por JVM para cada servlet, a menos que implemente SingleThreadModel.

SingleThreadModel en palabras simples dice que solo tiene que tener un hilo por instancia de Servlet, por lo que básicamente necesita crear una instancia por cada solicitud para manejarlo, lo que básicamente elimina todo el concepto de manejo de solicitudes de forma paralela y no se considera una buena práctica ya que la creación e inicialización del objeto servlet toma tiempo antes de que esté listo para procesar la solicitud.

Cuestiones relacionadas