Tabla de Contenidos

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.

1. Un servlet

@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

2. Ciclo de vida

@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.

3. Filtros

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í.

4. Qué resuelve y qué no

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.