Filtros de Servlet

Los filtros son clases Java que nos permiten interceptar una petición y modificarla antes de que sea procesada por el Servlet, o interceptar una respuesta antes que que la misma sea enviada al cliente, para crear estas clases es necesario implementar la interface javax.servlet.Filter, la cual define los siguientes tres métodos que debemos implementar:

  • init(FilterConfig cfg). Es invocado por el contenedor una vez que el filtro entra en funcionamiento.
  • destroy(). Este método lo llama el contenedor cuando el filtro de Servlet deja de funcionar.
  • doFilter(ServletRequest req, ServletResponse res, FilterChain chain). El contenedor llama a este método para cada solicitud de Servlet correlacionada con este filtro antes de invocar el Servlet. El Servlet original solicitado se ejecuta cuando el filtro llama al método chain.doFilter(...).

Diagrama básico de funcionamiento de un filtro.

    filtro-servlet

    Para la demostración de nuestro primer filtro usaremos la aplicación creada anteriormente en donde explicábamos como utilizar una plantilla Thymeleaf desde un Servlet, aquella plantilla tiene soporte para internacionalización, más específicamente soporta los idiomas inglés y español, lo que haremos será crear un filtro que nos permita cambiar el idioma usando un parámetro en la URL, por ejemplo:

    El parámetro es idioma con el valor "es" cambiamos a español y con "en" a ingles, esto es lo que tenemos del tutorial antes mencionado.

    @WebServlet("/")
    public class PrimerServlet extends HttpServlet {
    
        private PrimerThymeleaf primerThymeleaf;
        private ServletContext servletContext;
    
        @Override
        public void init(ServletConfig config) throws ServletException {
            servletContext = config.getServletContext();
            primerThymeleaf = new PrimerThymeleaf(servletContext);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setContentType("text/html;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
                
            WebContext ctx = new WebContext(request, response, servletContext, response.getLocale());
            ctx.setVariable("today", new Date());
            
            TemplateEngine engine = primerThymeleaf.getTemplateEngine();
            engine.process("home", ctx, response.getWriter());
        }
    }
    

    Esta clase responde a la petición HTTP GET procesando la plantilla indicada, lo que nos interesa observar es que al crear el objeto WebContext le pasamos el objeto Locale que define el idioma, el mismo es obtenido con el método response.getLocale(), el cual obtiene el objeto Locale basada en la cabecera Accept-Language proporcionada por el cliente.

    WebContext ctx = new WebContext(..., response.getLocale());
    

    Ahora lo que deseamos hacer es cambiar el Locale por medio de la URL, sin tener la necesidad de cambiar la cabecera Accept-Language en el navegador.

    Programando Nuestro Filtro

    Para este filtro los métodos init(...) y destroy() no requieren código, pero hay que sobre escribirlos para cumplir con la interface.

    Usaremos la anotación @WebFilter para definir el filtro, debemos indicar la URL con la que trabajara el filtro, para nosotros "/*" nos permite capturar todas las peticiones, esta anotación debe usarse sobre una clase que implemente la interface Filter.

    @WebFilter("/*")
    public class PrimerFiltro implements Filter {
    
        @Override
        public void init(FilterConfig config) throws ServletException {
            // nada por ahora...
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                throws IOException, ServletException {
            
            String idioma = req.getParameter("idioma");
            
            if(idioma != null) {
                if(idioma.equals("es") || idioma.equals("en")) {
                    res.setLocale(new Locale(idioma));
                }
            }
    
            chain.doFilter(req, res);       
        }
    
        @Override
        public void destroy() {
            // nada por ahora...
        }
    }
    

    Este filtro es bastante sencillo, primero lee el parámetro idioma, si el mismo está presente crea el nuevo objeto Locale y se lo asigna al objeto ServletResponse.

    String idioma = req.getParameter("idioma");
    
    if(idioma != null) {
        if(idioma.equals("es") || idioma.equals("en")) {
            res.setLocale(new Locale(idioma));
        }
    }
    

    Cualquier modificación a la petición, podemos hacerla antes de llamar al Servlet, para pasar el control de la petición al Servlet debemos invocar el siguiente método:

    chain.doFilter(req, res);
    

    Si lo deseamos podemos realizar alguna modificación a la respuesta generada por el Servlet antes de pasarla al cliente, esto lo haríamos después de invocar el método doFileter(...) antes mencionado.

    El resultado en el navegador web:

    Usando los filtros en servlets

    Filtros tutorial

    Recordemos que para agregar un parámetro a la URL debemos agregar el símbolo "?" luego de la variable con su valor.

    Si bien este filtro es bastante simple y lo que hicimos con él lo pudimos haber hecho desde el propio Servlet, la idea es comprender como un filtro puede interceptar una petición y modificarla antes de pasarla al Servlet o bien modificar la respuesta antes de que esta sea enviada al cliente.

    Descargar ejemplo: filtro-servlet.zip

    Comentarios

    Entradas populares de este blog

    Conectar SQL Server con Java

    Acceso a la webcam con OpenCV

    Procesamiento de imágenes en OpenCV

    Entrenar OpenCV en Detección de Objetos

    Analizador Léxico