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: