ServletContext
Cuando se inicia el contenedor de servlets (como Apache Tomcat ), desplegará y cargará todas sus aplicaciones web. Cuando se carga una aplicación web, el contenedor de servlet crea ServletContext
una vez y la mantiene en la memoria del servidor. La aplicación web de web.xml
y todos incluidos web-fragment.xml
se analiza archivos, y cada uno <servlet>
, <filter>
y <listener>
encontraron (o cada clase anotados con @WebServlet
, @WebFilter
y @WebListener
respectivamente) se instancia una vez y se mantienen en la memoria del servidor también. Para cada filtro instanciado, su init()
método se invoca con un nuevo FilterConfig
.
Cuando a Servlet
tiene un valor <servlet><load-on-startup>
o @WebServlet(loadOnStartup)
mayor que 0
, entonces su 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
es 1º, 2
es 2º, etc.). Si se especifica el mismo valor para más de un servlet, entonces cada uno de esos servlets se carga en el mismo orden en que aparecen en el web.xml
, web-fragment.xml
o @WebServlet
carga de clase. En el caso de que el valor de "carga al inicio" esté ausente, el init()
método se invocará siempre que la solicitud HTTP llegue a ese servlet por primera vez.
Cuando el contenedor de servlet finalice con todos los pasos de inicialización descritos anteriormente, ServletContextListener#contextInitialized()
se invocará.
Al cerrarse la contenedor de servlets abajo, descarga todas las aplicaciones Web, invoca el destroy()
método de todas sus servlets y filtros inicializados, y todo ServletContext
, Servlet
, Filter
y Listener
los casos están destrozados. Finalmente ServletContextListener#contextDestroyed()
se invocará el.
HttpServletRequest y HttpServletResponse
El contenedor de servlet está conectado a un servidor web que escucha las solicitudes HTTP en un determinado número de puerto (el puerto 8080 generalmente se usa durante el desarrollo y el puerto 80 en producción). Cuando un cliente (por ejemplo, usuario con un navegador web, o mediante programaciónURLConnection
) envía una solicitud HTTP, el contenedor servlet crea nueva HttpServletRequest
y HttpServletResponse
objetos y los pasa a través de cualquier definido Filter
en la cadena y, eventualmente, la Servlet
instancia.
En el caso de los filtros , doFilter()
se invoca el método. Cuando el código del contenedor de servlet llama chain.doFilter(request, response)
, la solicitud y la respuesta continúan al siguiente filtro, o presionan el servlet si no hay filtros restantes.
En el caso de los servlets , service()
se invoca el método. Por defecto, este método determina cuál de los doXxx()
métodos invocar en función 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 su URL, encabezados, cadena de consulta y cuerpo. El objeto de respuesta proporciona la capacidad de controlar y enviar la respuesta HTTP de la manera que desee, por ejemplo, permitiéndole 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, los objetos de solicitud y respuesta se reciclan y se ponen a disposición para su reutilización.
HttpSession
Cuando un cliente visita la aplicación web por primera vez y / o HttpSession
se obtiene por primera vez a través de request.getSession()
, el contenedor de servlet crea un nuevo HttpSession
objeto, genera un ID largo y único (que puede obtener session.getId()
) y lo almacena en el servidor memoria. El contenedor de servlets también establece una Cookie
en la Set-Cookie
cabecera de la respuesta HTTP con JSESSIONID
como su nombre y el identificador de sesión único como su valor.
Según la especificación de cookies HTTP (un contrato al que debe adherirse cualquier navegador web y servidor web decente), el cliente (el navegador web) debe enviar esta cookie en solicitudes posteriores en el Cookie
encabezado mientras la cookie sea válida ( es decir, la ID única debe referirse a una sesión no vencida y el dominio y la ruta son correctos). Usando el monitor de tráfico HTTP incorporado de su navegador, puede verificar que la cookie sea válida (presione F12 en Chrome / Firefox 23+ / IE9 +, y verifique la pestaña Red / Red ). El contenedor del servlet verificará el Cookie
encabezado de cada solicitud HTTP entrante en busca de la presencia de la cookie con el nombre JSESSIONID
y usará su valor (el ID de sesión) para obtener el asociado HttpSession
de la memoria del servidor.
El HttpSession
permanece vivo hasta que haya estado inactivo (es decir, no utilizado en una solicitud) durante más tiempo que el valor de tiempo de espera especificado en <session-timeout>
una configuración web.xml
. El valor de tiempo de espera predeterminado es 30 minutos. Por lo tanto, cuando el cliente no visita la aplicación web durante 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 servlet creará una nueva sesión.
En el lado del cliente, la cookie de sesión permanece viva mientras se ejecuta la instancia del navegador. Entonces, si el cliente cierra la instancia del navegador (todas las pestañas / ventanas), la sesión se descarta del lado del cliente. En una nueva instancia del navegador, la cookie asociada con la sesión no existiría, por lo que ya no se enviaría. Esto hace HttpSession
que se cree una completamente nueva, con una cookie de sesión completamente nueva que se utiliza.
En una palabra
- La
ServletContext
vida dura tanto como la aplicación web. Se comparte entre todas las solicitudes en todas las sesiones.
- La
HttpSession
vida dura mientras el cliente interactúa con la aplicación web con la misma instancia del navegador, y la sesión no ha expirado en el lado del servidor. Se comparte entre todas las solicitudes en la misma sesión.
- El
HttpServletRequest
y HttpServletResponse
vive desde el momento en que el servlet recibe una solicitud HTTP del cliente, hasta que llega la respuesta completa (la página web). Se no compartida en otro lugar.
- Todo
Servlet
, Filter
y Listener
casos viven tanto como vive la aplicación web. Se comparten entre todas las solicitudes en todas las sesiones.
- Cualquiera
attribute
que esté definido en ServletContext
, HttpServletRequest
y HttpSession
vivirá mientras viva el objeto en cuestión. 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 de ámbito como uno attribute
de sus ámbitos de coincidencia más cercanos.
Hilo de seguridad
Dicho esto, su mayor preocupación es posiblemente la seguridad del hilo . 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 subprocesos (léase: solicitudes HTTP) pueden hacer uso de la misma instancia. De lo contrario, sería demasiado costoso recrearlos init()
y destroy()
cada solicitud individual.
También debe darse cuenta de que nunca debe asignar ninguna solicitud o datos con alcance de sesión como una variable de instancia de un servlet o filtro. Se compartirá entre todas las demás solicitudes en otras sesiones. ¡Eso no es seguro para subprocesos! 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:
PHPSESSID
cookie, ASP.NET conASP.NET_SessionID
cookie, etc. Esa es también la razón por la que la reescritura de URL con;jsessionid=xxx
algunos marcos JSP / Servlet MVC automáticamente está mal vista. Solo asegúrese de que la ID de la sesión nunca se exponga en la URL o por otros medios en las páginas web para que el usuario final no sea atacado.Sesiones
En resumen: el servidor web emite un identificador único para cada visitante en su primera visita. El visitante debe traer esa identificación para que sea reconocido la próxima vez. Este identificador también permite al servidor segregar adecuadamente los objetos que posee una sesión contra la de otra.
Instanciación de servlet
Si load-on-startup es falso :
Si load-on-startup es verdadero :
Una vez que esté en el modo de servicio y en el ritmo, el mismo servlet funcionará en las solicitudes de todos los demás clientes.
¿Por qué no es una buena idea tener una instancia por cliente? Piensa en esto: ¿Contratarás un pizzero por cada pedido que llegue? Hazlo y estarás fuera del negocio en poco tiempo.
Sin embargo, conlleva un pequeño riesgo. Recuerde: este chico solo tiene toda la información de la orden en su bolsillo: por lo tanto, si no tiene cuidado con la seguridad del hilo en los servlets , puede terminar dando la orden incorrecta a un determinado cliente.
fuente
to many requests at this moment. try again later
La sesión en servlets de Java es lo mismo que la sesión en otros lenguajes como PHP. Es exclusivo del usuario. El servidor puede seguirlo de diferentes maneras, como cookies, reescritura de URL, etc. Este artículo de documentación de Java 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 que se deja 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. Consulte este artículo de Oracle para obtener más información sobre ambas preguntas.
Editar Hay un excelente tutorial aquí sobre cómo trabajar con la sesión dentro de los servlets. Y aquí hay un capítulo de Sun sobre Java Servlets, qué son y cómo usarlos. Entre esos dos artículos, debería poder responder a todas sus preguntas.
fuente
ServletContext
objeto. Ese objeto tiene cero, uno o más objetos de sesión: una colección de objetos de sesión. Cada sesión se identifica mediante algún tipo de cadena de identificación, como se ve en los dibujos animados en otra respuesta. Ese identificador se rastrea en el cliente mediante cookies o reescritura de URL. Cada objeto de sesión tiene sus propias variables.Cuando se inicia el contenedor de servlets (como Apache Tomcat), se leerá del archivo web.xml (solo uno por aplicación) si algo sale mal o muestra un error en la consola del lado del contenedor; de lo contrario, se desplegará y cargará toda la web aplicaciones utilizando web.xml (denominado así como descriptor de implementación).
Durante la fase de creación de instancias del servlet, la instancia de servlet está lista pero no puede atender la solicitud del cliente porque falta dos datos:
1: información de contexto
2: información de configuración inicial
El motor de servlet crea el objeto de interfaz servletConfig que encapsula la información que falta arriba en él. El motor de servlet llama init () del servlet al proporcionar referencias de objeto servletConfig como argumento. Una vez que init () se ejecuta por completo, el servlet está listo para atender la solicitud del cliente.
P) En la vida útil del servlet, ¿cuántas veces ocurre la instanciación y la inicialización?
A) solo una vez (por cada solicitud de cliente se crea un nuevo subproceso) solo una instancia del servlet sirve cualquier número de solicitud del cliente, es decir, después de servir un servidor de solicitud de cliente no muere. Espera las solicitudes de otros clientes, es decir, qué limitación de CGI (para cada solicitud de cliente que se crea un nuevo proceso) se supera con el servlet (internamente el motor de servlet crea el hilo).
P) ¿Cómo funciona el concepto de sesión?
A) cada vez que se llama a getSession () en el objeto HttpServletRequest
Paso 1 : el objeto de solicitud se evalúa para la ID de sesión entrante.
Paso 2 : si la ID no está disponible, se crea un nuevo objeto HttpSession y se genera su ID de sesión correspondiente (es decir, de HashTable), la ID de sesión se almacena en el objeto de respuesta httpservlet y la referencia del objeto HttpSession se devuelve al servlet (doGet / doPost) .
Paso 3 : si la ID disponible no se crea el nuevo objeto de sesión, la ID de sesión se recoge de la solicitud de búsqueda de objetos que se realiza en la colección de sesiones utilizando la ID de sesión como clave.
Una vez que la búsqueda es exitosa, 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 sale del código de servlet al cliente, no olvide que el objeto de sesión está retenido por el contenedor de servlet, es decir, el motor de servlet
2) el subprocesamiento múltiple se deja a la gente de desarrolladores de servlets para implementar, es decir, manejar las múltiples solicitudes del cliente, nada de lo que preocuparse por el código multiproceso
Forma corta:
Se crea un servlet cuando se inicia la aplicación (se implementa en el contenedor del servlet) o cuando se accede por primera vez (según la configuración de carga al inicio) cuando se instancia el 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 aconsejable tener ninguna sincronización, y debe evitar las variables de instancia del servlet cuando la aplicación no se implementa (el contenedor del servlet se detiene), se llama al método destroy ().
fuente
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 en el inicio con el
<load-on-startup>
elemento enweb.xml
). La misma instancia se utiliza para atender solicitudes posteriores.fuente
La Especificación de 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 subprocesamiento múltiple, Página 9):
fuente
Como queda claro en las explicaciones anteriores, al implementar SingleThreadModel , el servlet puede garantizar la seguridad de la rosca mediante el contenedor de servlets. La implementación del contenedor puede hacer esto de 2 maneras:
1) Solicitudes de serialización (colas) a una sola instancia: esto es similar a un servlet que NO implementa SingleThreadModel PERO sincronizando los métodos de servicio / doXXX; O
2) Crear un grupo de instancias, que es una mejor opción y una compensación entre el esfuerzo de arranque / inicialización / tiempo del servlet frente a los parámetros restrictivos (tiempo de memoria / CPU) del entorno que aloja el servlet.
fuente
No. Los servlets no son seguros para subprocesos
Esto permite acceder a más de un hilo a la vez
si quieres que sea Servlet como Thread safe., U puedes elegir
Implement SingleThreadInterface(i)
que es una interfaz en blanco no haymé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
palabra clave delante del método
Ejemplo::
o podemos poner el bloque put del código en el bloque Sincronizado
Ejemplo::
Siento que el bloqueo sincronizado es mejor que hacer todo el método
Sincronizado
fuente