05 - Servlets

Un servlet es un componente Java que procesa peticiones HTTP dentro de un contenedor. El desarrollador escribe el método que responde; el contenedor se ocupa de sockets, hilos, parseo y envío.

@WebServlet("/books")
public class BookServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
            throws IOException {
        String id = request.getParameter("id");

        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().print("{\"id\":" + id + "}");
    }

    @Override
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws IOException {
        // procesar el cuerpo y crear el recurso
        response.setStatus(HttpServletResponse.SC_CREATED);
    }
}

Elemento Función
HttpServlet Clase base con el ciclo de vida gestionado por el contenedor
doGet / doPost Responden a los métodos HTTP correspondientes
HttpServletRequest Petición: parámetros, cabeceras, cuerpo
HttpServletResponse Respuesta: estado, cabeceras, cuerpo
@WebServlet Asocia el servlet con una ruta
  • init() — el contenedor crea el servlet una vez al arrancar (o a la primera petición).
  • service() — cada petición delega en doGet/doPost. Una sola instancia atiende todas las peticiones, cada una en un hilo del pool del contenedor.
  • destroy() — el contenedor lo retira al parar.

@WebServlet("/counter")
public class CounterServlet extends HttpServlet {
    private int counter = 0;   // ¡compartido por todas las peticiones!

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        counter++;   // condición de carrera entre peticiones concurrentes
        response.getWriter().print(counter);
    }
}

El estado de instancia del servlet es compartido: las reglas de hilos del tema 03 se aplican tal cual. El estado por petición debe ser local o gestionarse con cuidado.

Un filtro se ejecuta en la cadena antes (o después) del servlet. Sirve para lógica transversal: registro, compresión, autenticación.

@WebFilter("/*")
public class TokenFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        String header = ((HttpServletRequest) request).getHeader("Authorization");

        if (header != null && header.startsWith("Bearer ")) {
            // validar el token; si es válido, continuar
            chain.doFilter(request, response);
        } else {
            ((HttpServletResponse) response).setStatus(401);
        }
    }
}

chain.doFilter(…) pasa al siguiente filtro o al servlet; sin llamarlo, la petición termina ahí.

Resuelve el contenedor Sigue siendo responsabilidad del desarrollador
Sockets, pool de hilos, HTTP Qué hace cada ruta (la lógica)
Enrutado a servlets por ruta Estructura de la aplicación
Parseo de parámetros y cabeceras Reglas de negocio y acceso a datos
Devolución de errores de protocolo Cuerpo y formato de los datos (JSON)
Un servlet atiende muchas peticiones con una sola instancia: no guardes en sus campos nada que pertenezca a una petición concreta. La autenticación por token se resuelve con filtros que validan la cabecera Authorization; sin sesiones de servidor.
  • clase/daw/si/1eval/servlets2.txt
  • Última modificación: 2026/10/12 13:02
  • por cesguiro