The Web Container Model - Filters (SCWCD)

Objetivos:

Section 3: The Web Container Model (FILTERS)

3.3- Describe the Web container request processing model; write and configure a filter; create a request or response wrapper; and given a design problem, describe how to apply a filter or a wrapper.



Que es un filtro (filter)?
Para una aplicación web, un filtro es un componente web el cuál “filtra” las peticiones y respuestas que se realizan entre en cliente y el servidor. Estos filtros permiten monitorear los mensajes enviados antes de que los mismos alcancen su destino. La existencia de un filtro es transparente tanto al cliente como también al recurso (como puede ser un servlet).
También se puede emplear una cadena de filtros, en la cual los filtros se ejecutan uno seguido de otro (en cadena). Un filtro permite procesar una petición y pasarla (la petición procesada) al siguiente filtro de la cadena. Similarmente, cada filtro se ejecutará en orden inverso procesando la respuesta antes de que sea devuelta al cliente.

Como trabaja la filtración
Cuando el contenedor de servlets recibe una petición a un recurso, se verifica la existencia de filtros asociados al recurso. Si existe algún filtro asociado, el contenedor dirige la petición al filtro en vez de al recurso. Luego de que el filtro procesa la petición, realiza una de las siguientes acciones:
  • Genera la respuesta, por el mismo, y se la retorna al cliente.
  • Pasa la petición (modificada o no) al siguiente filtro de la cadena (si existe) o al recurso.
  • Dirige la petición a un recurso diferente.
Cuando se devuelve la respuesta desde el recurso, esta atraviesa el mismo conjunto de filtros en orden inverso. Cada filtro en la cadena puede modificar la respuesta.

La API de filtros (Filter API)
Interfaces del paquete javax.servlet:

javax.servlet.Filter: Todos los filtros deben implementar esta interface. Define tres métodos:
  • void init (FilterConfig) throws ServletException: El contenedor de servlets invoca este método sobre una instancia solo una vez. La implementación típica de este método es almacenar la instancia FilterConfig, para luego ser utilizada. Este método es una analogía del método init(ServletConfig) de la interface Servlet.
  • void doFilter (ServletRequest, ServletResponse, FilterChain) throws ServletException, IOException: El contenedor de servlets invoca este método para cada petición que sea mapeada con un filtro. Una implementación típica de una aplicación web, castea las instancias de ServletRequest y ServletResponse a sus correspondientes implementaciones del protocolo http, para luego realizar el procesamiento por el cual se creó el filtro. Este método es una analogía del método service(ServletRequest, ServletResponse) de la interface Servlet.
  • void destroy (): El contenedor de servlets invoca este método para liberar los recursos del filtro y realizar tareas de limpieza, antes de que el mismo sea eliminado.

javax.servlet.FilterChain: El contenedor de servlets provee una implementación para esta interface y pasa una instancia de la misma al método doFilter() del filtro. Posee solo un método:
  • void doFilter (ServletRequest, ServletResponse): Pasa la petición  al próximo componente en la cadena, otro filtro o el recurso original.

javax.servlet.FilterConfig: El contenedor de servlets provee una implementación para esta interface. Al igual que ServletConfig, la instancia se pasa a través del método init(FilterConfig). Esta interface provee métodos para acceder a los parámetros de inicialización de un filtro, y algunos otros datos:
  • String getFilterName (): Devuelve el nombre del filtro especificado en el archivo web.xml.
  • String getInitParameter (String): Devuelve el valor del parámetro especificado en el archivo web.xml.
  • Enumeration getInitParameterNames (): Devuelve una instancia Enumeration con los nombres de los parámetros de inicialización definidos en el archivo web.xml.
  • ServletContext getServletContext (): Devuelve la instancia de ServletContext asociada a la aplicación web.
Clases del paquete javax.servlet:
  • javax.servlet.ServletRequestWrapper
  • javax.servlet.ServletResponseWrapper
Clases del paquete javax.servlet.http:
  • javax.servlet.http.HttpServletRequestWapper
  • javax.servlet.http.HttpServletResponseWrapper
Estas últimas cuatro clases wrappers, funcionan de la misma manera. Toman una petición o una respuesta (ServletRequest o ServletResponse) en su constructor y delegan todas las invocaciones de métodos a ese objeto. Esto permite extender estas clases y sobrescribir cualquier método para personalizar un comportamiento.

Configurar un filtro
Para definir un filtro en el archivo web.xml, se debe utilizar los elementos <filter> y <filter-mapping>.
<!ELEMENT filter (icon?, filter-name, display-name?, description?, filter-class, init-param*) >
<!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name)) >

<filter>: Cada elemento de este tipo, introduce un nuevo filtro en la aplicación web. Este elemento puede contener varios elementos más. Algunos opcionales como: <icon>, <display-name> y <init-param>. Otros obligatorios como:
  • <filter-name>: Define el nombre del filtro dentro del archivo de configuración.
  • <filter-class>: Define la clase utilizada para instanciar el filtro.
<filter-mapping>: Al igual que <servlet-mapping>, este elemento asocia un filtro con un conjunto de URLs. Contiene los elementos:
  • <filter-name>: Identifica el filtro a asociar.
  • <url-pattern>: Se utiliza para aplicar el filtro a las peticiones que concuerden con el patrón URL.
  • <servlet-name>: Se utiliza para aplicar el filtro a todas las peticiones que se realicen al servlet asociado.
Solo puede existir un subelemento <url-pattern> o <servlet-name>, dentro un mismo <filter-mapping>.

Configurando cadenas de filtros
Las cadenas de filtros pueden ser configuradas utilizando múltiples elementos <filter-mapping>. Cuando el contenedor de servlets recibe una petición, este busca todos los mapeos de filtros que concuerdan la URI con el patrón URL. Este se considera el primer conjunto de filtros a aplicar al recurso. Luego, se buscan todos los mapeos de filtros con el nombre del servlet correspondiente. Este se convierte en el segundo conjunto de filtros en la cadena de filtros. En ambos conjuntos, el orden de los filtros se corresponde al orden de declaración de los mismos en el archivo web.xml.
El contenedor primero invoca a los filtros del primer conjunto antes que los del segundo.

Ejecución de filtros
Como la especificación de Servlets 2.4 permite invocar servlets de las siguientes maneras:
  • Como un resultado del método RequestDispatcher.forward().
  • Como un resultado del método RequestDispatcher.include().
  • En páginas de error.
Un filtro solo es invocado con peticiones entrantes (desde el cliente). Pero el archivo web.xml permite especificar los modos de invocación de un filtro:
<filter-mapping>
    <filter-name>AccessLog</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>
  • El elemento <filter-name> es obligatorio.
  • Se debe usar un elemento <url-pattern> o <servlet-name>, no se pueden usar ambos dentro de un mismo elemento <filter-mapping>.
  • Se pueden usar de 0 a 4 subelementos <dispatcher> dentro de un elemento <filter-mapping>.
  • Por defecto (si no se especifica ningún subelemento <dispatcher>) los filtros solo se aplican para peticiones entrantes a la aplicación. Es decir, solo el valor REQUEST es aplicado por defecto
  • Si el contenedor no puede encontrar el recurso solicitado por una petición, ningún filtro correspondiente a la misma se invoca. Los filtros solo se invocan si existe el recurso original.

1 comentarios :: The Web Container Model - Filters (SCWCD)

  1. Que buen post, me has aclarado algunas dudas, ya que empiezo a aprender Struts2, y quiero resolver todas las dudas para tener bases firmes.

Publicar un comentario