Pregunta ¿Cómo funcionan los servlets? Instanciación, sesiones, variables compartidas y multihilo


Supongamos que tengo un servidor web que contiene numerosos servlets. Para la información que pasa entre esos servlets, estoy configurando las variables de sesión y de instancia.

Ahora, si 2 o más usuarios envían solicitudes a este servidor, ¿qué ocurre con las variables de sesión? ¿Serán todos comunes para todos los usuarios o serán diferentes para cada usuario? Si son diferentes, ¿cómo pudo el servidor diferenciar entre diferentes usuarios?

Una pregunta más similar, si hay n los usuarios que acceden a un servlet en particular, ¿este servlet se instancia solo la primera vez que el primer usuario accedió o se crea una instancia para todos los usuarios por separado? En otras palabras, ¿qué ocurre con las variables de instancia?


989
2018-06-24 00:16


origen


Respuestas:


ServletContext

Cuando el contenedor servlet (como Apache Tomcat) se inicia, desplegará y cargará todas sus aplicaciones web. Cuando se carga una aplicación web, el contenedor de servlets crea el ServletContext una vez y lo mantiene en la memoria del servidor. La aplicación web web.xml archivo es analizado, y cada <servlet>, <filter> y <listener> encontrado (o cada clase anotada con @WebServlet, @WebFilter y @WebListener respectivamente) se crea una instancia una vez y se guarda en la memoria del servidor también. Para cada filtro instanciado, es init() método se invoca con un nuevo FilterConfig.

Cuando el contenedor de servlets se apaga, descarga todas las aplicaciones web, invoca el destroy() método de todos sus servlets y filtros inicializados, y todos ServletContext, Servlet, Filter y Listener las instancias son destruidas.

Cuando un Servlet tiene un <servlet><load-on-startup> o @WebServlet(loadOnStartup) valor mayor que 0, es init() método también se invoca durante el inicio con un nuevo ServletConfig. Esos servlets se inicializan en el mismo orden especificado por ese valor (1 -> 1 °, 2 -> 2 °, etc.). Si se especifica el mismo valor para más de un servlet, cada uno de esos servlets se carga en el orden en que aparecen en el web.xml, o @WebServlet carga de clases En el caso de que el valor de "carga al inicio" esté ausente, el init() El método se invocará cada vez que la solicitud HTTP golpee ese servlet por primera vez.

HttpServletRequest y HttpServletResponse

El contenedor del servlet está conectado a un servidor web que escucha las solicitudes HTTP en un determinado número de puerto (el puerto 8080 se usa generalmente durante el desarrollo y el puerto 80 en producción). Cuando un cliente (usuario con un navegador web) envía una solicitud HTTP, el contenedor servlet crea una nueva HttpServletRequest y HttpServletResponse objetos y los pasa a través de cualquier definido Filter cadena y, finalmente, la Servlet ejemplo.

En el caso de filtros, el doFilter() método es invocado Cuando su código llama chain.doFilter(request, response), la solicitud y la respuesta continúan con el siguiente filtro o acciona el servlet si no hay filtros restantes.

En el caso de servlets, el service() método es invocado Por defecto, este método determina cuál de los doXxx() métodos para invocar basados ​​fuera de request.getMethod(). Si el método determinado está ausente del servlet, se devuelve un error HTTP 405 en la respuesta.

El objeto de solicitud proporciona acceso a toda la información sobre la solicitud HTTP, como sus encabezados y cuerpo. El objeto de respuesta proporciona la capacidad de controlar y enviar la respuesta HTTP de la manera que desee, por ejemplo, lo que le permite configurar los encabezados y el cuerpo (generalmente con contenido HTML generado a partir de un archivo JSP). Cuando la respuesta HTTP se confirma y finaliza, tanto los objetos de solicitud como de respuesta se reciclan y se vuelven a utilizar.

HttpSession

Cuando un cliente visita la aplicación web por primera vez y / o el HttpSession se obtiene por primera vez a través de request.getSession(), el contenedor servlet crea un nuevo HttpSession objeto, genera una identificación larga y única (que puede obtener session.getId()), y almacenarlo en la memoria del servidor. El contenedor servlet también establece un Cookie en el Set-Cookie encabezado de la respuesta HTTP con JSESSIONID como su nombre y la ID de sesión única como su valor.

Según el Especificación de cookies HTTP (un contrato al que deben adherirse un navegador web decente y un servidor web), se requiere que el cliente (el navegador web) envíe esta cookie en solicitudes posteriores en el Cookie encabezado mientras la cookie sea válida (es decir, la ID única debe hacer referencia a una sesión no vencida y el dominio y la ruta son correctos). Usando el monitor de tráfico HTTP integrado en su navegador, puede verificar que la cookie sea válida (presione F12 en Chrome / Firefox 23+ / IE9 +, y verifique Red / Red lengüeta). El contenedor servlet verificará Cookie encabezado de cada solicitud HTTP entrante para la presencia de la cookie con el nombre JSESSIONID y use su valor (la ID de la sesión) para obtener el HttpSession desde la memoria del servidor.

los HttpSession permanece vivo hasta que no se haya usado por más del valor de tiempo de espera especificado en <session-timeout>, un ajuste en web.xml. El valor de tiempo de espera predeterminado es 30 minutos. Entonces, cuando el cliente no visita la aplicación web por más tiempo que el especificado, el contenedor de servlets destruye la sesión. Cada solicitud posterior, incluso con la cookie especificada, ya no tendrá acceso a la misma sesión; el contenedor de servlets creará una nueva sesión.

En el lado del cliente, la cookie de sesión permanece activa mientras se ejecuta la instancia del navegador. Por lo tanto, si el cliente cierra la instancia del navegador (todas las pestañas / ventanas), la sesión se descarta por el lado del cliente. En una nueva instancia del navegador, la cookie asociada a la sesión no existiría, por lo que ya no se enviaría. Esto causa un completamente nuevo HTTPSession para ser creado, con una cookie de sesión completamente nueva que comienza a usarse.

En una palabra

  • los ServletContext vive mientras viva la aplicación web. Se comparte entre todas solicitudes en todas sesiones
  • los HttpSession vive mientras el cliente esté interactuando con la aplicación web con la misma instancia del navegador, y la sesión no ha excedido el tiempo de espera en el servidor. Se comparte entre todas solicitudes en el mismo sesión.
  • los HttpServletRequest y HttpServletResponse en vivo desde el momento en que el servlet recibe una solicitud HTTP del cliente, hasta que llega la respuesta completa (la página web). Es no compartido en otro lugar.
  • Todas Servlet, Filter y Listener las instancias viven mientras viva la aplicación web. Se comparten entre todas solicitudes en todas sesiones
  • Alguna attribute eso está definido en ServletContext, HttpServletRequest y HttpSession vivirá mientras el objeto en cuestión viva. El objeto en sí mismo representa el "alcance" en los marcos de gestión de beans como JSF, CDI, Spring, etc. Esos marcos almacenan sus beans con ámbito como una attribute de su alcance coincidente más cercano.

Seguridad de subprocesos

Dicho esto, su mayor preocupación es posiblemente hilo de seguridad. Ahora debe saber que los servlets y los filtros se comparten entre todas las solicitudes. Eso es lo bueno de Java, es multiproceso y diferentes hilos (leer: solicitudes HTTP) pueden hacer uso de la misma instancia. De lo contrario, sería demasiado caro para recrear, init() y destroy() ellos para cada solicitud individual.

También debes darte cuenta de que deberías Nunca asignar cualquier solicitud o datos de ámbito de sesión como una ejemplo variable de un servlet o filtro. Se compartirá entre todas las demás solicitudes en otras sesiones. Eso es no ¡a salvo de amenazas! El siguiente ejemplo ilustra esto:

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

Ver también:


1623
2018-06-24 02:41



Sesiones

enter image description here enter image description here

En resumen: el servidor web emite un identificador único para cada visitante sobre su primero visitar. El visitante debe traer esa identificación para que sea reconocido la próxima vez. Este identificador también permite que el servidor segregue adecuadamente los objetos propiedad de una sesión frente a la de otra.

Instanciación de servlet

Si carga-en-inicio es falso:

enter image description here enter image description here

Si carga-en-inicio es cierto:

enter image description here enter image description here

Una vez que está en el modo de servicio y en el surco, el mismo servlet trabajará en las solicitudes de todos los demás clientes.

enter image description here

¿Por qué no es una buena idea tener una instancia por cliente? Piense en esto: ¿Contratará a un tipo de pizza por cada orden que venga? Hazlo y estarías fuera del negocio en muy poco tiempo.

Sin embargo, viene con un pequeño riesgo. Recuerde: este hombre soltero guarda toda la información del pedido en su bolsillo: así que si no tiene cuidado con seguridad de hilo en los servlets, él puede terminar dando la orden incorrecta a cierto cliente.


394
2017-07-06 16:38



La sesión en los servlets de Java es la misma que en otros lenguajes, como PHP. Es único para el usuario. El servidor puede rastrearlo de diferentes maneras, como cookies, reescritura de URL, etc. Documento Java el artículo lo explica en el contexto de los servlets de Java e indica que exactamente cómo se mantiene la sesión es un detalle de implementación dejado a los diseñadores del servidor. La especificación solo estipula que debe mantenerse como único para un usuario a través de múltiples conexiones al servidor. Revisa este artículo de Oracle para más información sobre sus dos preguntas.

Editar Hay un excelente tutorial aquí sobre cómo trabajar con sesión dentro de servlets. Y aquí es un capítulo de Sun sobre Java Servlets, qué son y cómo usarlos. Entre esos dos artículos, debería ser capaz de responder todas sus preguntas.


40
2018-06-24 00:20



Cuando el servletcontainer (como Apache Tomcat) se inicia, se leerá desde el archivo web.xml (solo uno por aplicación) si algo sale mal o aparece un error en la consola lateral del contenedor; de lo contrario, se implementará y cargará todas las aplicaciones web mediante web. .xml (llamado así como descriptor de despliegue).

Durante la fase de creación de instancias de servlet, servletInstance está listo pero no puede atender la solicitud del cliente porque falta información con dos elementos:
1: información de contexto
2: información de configuración inicial

El motor Servlet crea un objeto de interfaz servletConfig que encapsula la información que falta más arriba. servlet engine llama a init () de servlet al proporcionar referencias de objeto servletConfig como argumento. Una vez que init () se ha ejecutado, el servlet está listo para server la solicitud del cliente.

P) En el tiempo de vida de servlet, ¿cuántas veces ocurre la instanciación y la incialización?

A) solo una vez (para cada solicitud del cliente, se crea un nuevo hilo) solo una instancia del servlet sirve cualquier número de la solicitud del cliente, es decir, después de servir un servidor de solicitud del cliente no muere. Espera otras solicitudes de clientes es decir, qué CGI (para cada cliente solicita que se cree un nuevo proceso) la limitación se supera con servlet (internamente el motor de servlet crea el hilo).

P) ¿Cómo funciona el concepto de sesión?

A) siempre que se llame a getSession () en el objeto HttpServletRequest

Paso 1: el objeto request se evalúa para la ID de la sesión entrante.

Paso 2: si ID no está disponible, se crea un nuevo objeto HttpSession y se genera su ID de sesión correspondiente (es decir, de HashTable). ID de sesión se almacena en el objeto de respuesta httpservlet y la referencia del objeto HttpSession se devuelve a servlet (doGet / doPost).

Paso 3: si ID no está disponible, el nuevo objeto de sesión no se crea ID de sesión se recoge de la búsqueda de objeto de solicitud se realiza en la colección de sesiones mediante el uso de ID de sesión como la clave.

Una vez que la búsqueda tiene éxito, la ID de sesión se almacena en HttpServletResponse y las referencias de objetos de sesión existentes se devuelven a doGet () o doPost () de UserDefineservlet.

Nota:

1) cuando el control se va del código de servlet al cliente, no olvide que el objeto de sesión está siendo retenido por servletcontainer, es decir, servletengine

2) el subprocesamiento múltiple se deja a las personas de servlets devlopers para implementar, es decir, manejar la solicitud múltiple del cliente, nada que preocuparse por el código multithread

Forma incompleta:

Se crea un servlet cuando se inicia la aplicación (se implementa en el contenedor de servlets) o cuando se accede por primera vez (dependiendo de la configuración de carga al inicio) cuando se crea una instancia del servlet, se llama al método init () del servlet entonces el servlet (su única instancia) maneja todas las solicitudes (su método service () es llamado por múltiples hilos). Es por eso que no es recomendable tener ninguna sincronización en él, y debe evitar variables de instancia del servlet cuando la aplicación no está desplegada (el contenedor de servlets se detiene), se llama al método destroy ().


30
2018-02-22 12:54



Sesiones- lo que dijo Chris Thompson.

Instanciación - se crea una instancia de un servlet cuando el contenedor recibe la primera solicitud asignada al servlet (a menos que el servlet esté configurado para cargarse al inicio con el <load-on-startup> elemento en web.xml) La misma instancia se usa para atender solicitudes posteriores.


20
2018-06-24 00:27



La especificación del servlet JSR-315 Define claramente el comportamiento del contenedor web en los métodos de servicio (y doGet, doPost, doPut, etc.) (2.3.3.1 Problemas de multihilo, página 9):

Un contenedor de servlet puede enviar solicitudes simultáneas a través del servicio   método del servlet. Para manejar las solicitudes, el Desarrollador de Servlets   debe hacer las disposiciones adecuadas para el procesamiento concurrente con múltiples   hilos en el método de servicio.

Aunque no se recomienda, una alternativa para el Desarrollador es   implementar la interfaz SingleThreadModel que requiere el contenedor   para garantizar que solo hay un hilo de solicitud a la vez en el   método de servicio. Un contenedor de servlet puede satisfacer este requisito   serialización de solicitudes en un servlet o manteniendo un grupo de servlets   instancias. Si el servlet es parte de una aplicación web que ha sido   marcado como distribuible, el contenedor puede mantener un grupo de servlet   instancias en cada JVM en que se distribuye la aplicación.

Para los servlets que no implementan la interfaz SingleThreadModel, si el   método de servicio (o métodos como doGet o doPost que son   despachado al método de servicio de la clase abstracta HttpServlet)   se ha definido con la palabra clave sincronizada, el contenedor de servlets   no puede usar el enfoque de grupo de instancias, pero debe serializar las solicitudes   a traves de. Se recomienda encarecidamente que los desarrolladores no se sincronicen   el método de servicio (o métodos enviados a él) en estos   circunstancias debido a los efectos perjudiciales sobre el rendimiento


13
2018-03-05 11:41



No. Los servlets son no hilo seguro

The is permite acceder a más de un hilo a la vez

si quieres que sea Servlet como Thread safe., U puede ir por

Implement SingleThreadInterface(i)  que es una interfaz en blanco, no hay

métodos

o podemos ir por métodos de sincronización

podemos hacer que todo el método de servicio esté sincronizado mediante el uso sincronizado

keword delante del método

Ejemplo::

public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException

o podemos poner el bloque del código en el bloque sincronizado

Ejemplo::

Synchronized(Object)

{

----Instructions-----

}

Siento que el bloqueo sincronizado es mejor que hacer todo el método

Sincronizado


0
2018-04-14 15:32