Controlador PersonaControladorServlet - eliizquierdo/material_programacion_avanzada2026 GitHub Wiki

📦 Proyecto: mini-crud0 (Fase 1) — ⬇️ Descargar ZIP · ☁️ Abrir en Codespace

Controlador en Java Web (Servlet)

Vamos a analizar cómo este servlet actúa como controlador dentro de una aplicación Java web.

¿Qué hace este código?

  • Maneja solicitudes HTTP GET y POST
  • Interactúa con un objeto de tipo PersonaDAO (modelo de acceso a datos)
  • Redirige a formularios o vistas según la acción recibida
  • Implementa el patrón Post-Redirect-Get (PRG)

Solicitudes GET:

  • action=agregar → abre /WEB-INF/vista/persona-form.jsp (formulario)
  • action=listar → ejecuta listar() → abre /WEB-INF/vista/persona-lista.jsp
  • Sin action o action desconocida → ejecuta listar() por defecto

Solicitudes POST:

  • action=agregar → procesa datos y aplica PRG (Post-Redirect-Get)

Nota: La firma de los métodos doGet y doPost incluye throws ServletException, IOException aunque no siempre escribamos código que lance esas excepciones. Esto es porque la API del servlet define que estos métodos pueden lanzar esos errores al procesar la petición (por ejemplo, si falla un forward o al escribir en la respuesta). Por tanto, siempre debemos mantener esa parte de la firma al sobrescribirlos.

Analicemos el código:

package controlador;

import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;

import modelo.dao.PersonaDAO;
import modelo.vo.PersonaVO;

@WebServlet("/persona")
public class PersonaControladorServlet extends HttpServlet {
    private final PersonaDAO dao = new PersonaDAO();

    // ======================== GET ========================
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String action = request.getParameter("action");
        if (action == null)
            action = "";

        switch (action) {
            case "agregar": // mostrar formulario de alta (GET)
                request.getRequestDispatcher("/WEB-INF/vista/persona-form.jsp")
                        .forward(request, response);
            break;

            case "listar": // listar explícito
                listar(request, response);
                break;

            default: // sin action o desconocida → listar
                listar(request, response);
                break;
        }
    }

    // ======================== POST ========================
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");
        if (action == null) {
            response.sendRedirect(request.getContextPath() + "/persona");
            return;
        }

        switch (action) {
            case "agregar":
                agregar(request, response);
                break;
            default:
                response.sendRedirect(request.getContextPath() + "/persona");
        }
    }

    // ===================== Acciones privadas =====================
    private void agregar(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        int codigo = Integer.parseInt(request.getParameter("codigo"));
        String nombre = request.getParameter("nombre");
        dao.agregar(new PersonaVO(codigo, nombre));
        response.sendRedirect(request.getContextPath() + "/persona"); // PRG → listar
    }

    private void listar(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("personas", dao.getLista());
        request.getRequestDispatcher("/WEB-INF/vista/persona-lista.jsp")
                .forward(request, response);
    }
}

1) Encabezado del servlet

@WebServlet("/persona")
public class PersonaControladorServlet extends HttpServlet {
    private final PersonaDAO dao = new PersonaDAO();

¿Qué hace?

  • La anotación @WebServlet("/persona") indica que este servlet atiende la URL /persona
  • Hereda de HttpServlet, por lo que sobrescribe doGet() y doPost() para manejar las solicitudes del navegador
  • Esto nos permite programar acciones diferentes según el tipo de solicitud que se recibe del navegador

El atributo dao

private final PersonaDAO dao = new PersonaDAO();

Esta línea declara un atributo de instancia del servlet. Veamos qué significa cada parte:

  • private → solo es visible dentro de PersonaControladorServlet. Nadie de afuera puede acceder al DAO directamente.
  • final → la referencia dao no puede reasignarse. Una vez que apunta al objeto PersonaDAO creado al iniciar el servlet, siempre apuntará a ese mismo objeto. No significa que el objeto sea inmutable; significa que no se puede escribir dao = new PersonaDAO() en otro lugar del código.
  • new PersonaDAO() → se crea una instancia del DAO cuando Tomcat inicializa el servlet.

¿Por qué final y no static?

Con static, el atributo pertenecería a la clase en lugar de a la instancia, y sería compartido entre todas las instancias del servlet:

// Con static: UN solo DAO compartido por TODAS las instancias de la clase
private static final PersonaDAO dao = new PersonaDAO();

// Sin static (lo que usamos): UN DAO por instancia del servlet
private final PersonaDAO dao = new PersonaDAO();
private final private static final
Pertenece a La instancia del servlet La clase
Cuántos objetos DAO Uno por instancia Uno compartido por todas
Cuándo se crea Al instanciar el servlet Al cargar la clase

En la práctica, Tomcat normalmente crea una sola instancia del servlet para atender todas las peticiones, por lo que en este caso el efecto es similar. Sin embargo, usar static introduce un acoplamiento global innecesario y puede causar problemas si el DAO guardara estado entre peticiones. La convención en diseño MVC es preferir atributos de instancia (final sin static).

💡 Para explorar más: se puede consultar esta explicación adicional generada con IA: Gemini — ¿Por qué final y no static?

2) Procesar solicitudes GET (mostrar datos o formularios)

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

Vamos a procesar solicitudes GET, que son las que se envían, por ejemplo, cuando se carga una página en el navegador.

Dentro de este método:

String action = request.getParameter("action");
if (action == null)
    action = "";
switch (action) {
    case "agregar": // mostrar formulario de alta
        request.getRequestDispatcher("/WEB-INF/vista/persona-form.jsp")
                .forward(request, response);
        break;
    case "listar": // listar explícito
        listar(request, response);
        break;
    default: // sin action o desconocida 
        listar(request, response);
        break;
}

¿Qué pasa aquí?

action=agregar → formulario de alta Envía al usuario a /WEB-INF/vista/persona-form.jsp, un formulario vacío para crear una persona nueva.

action=listar o (default) Si action = listar o es distinta, se llama a listar(...) para mostrar todas las personas en /WEB-INF/vista/persona-lista.jsp.

2.1) Método auxiliar: listar

private void listar(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    request.setAttribute("personas", dao.getLista());
    request.getRequestDispatcher("/WEB-INF/vista/persona-lista.jsp")
            .forward(request, response);
}

¿Qué hace? Pide la lista al DAO, la guarda como atributo personas y hace forward al JSP del listado para que se renderice la tabla.

3) Procesar solicitudes POST (enviar datos)

@Override
protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

Aquí vamos a manejar datos que el usuario envía a través del formulario, como cuando hace clic en "Agregar".

request.setCharacterEncoding("UTF-8");
String action = request.getParameter("action");
if (action == null) {
    response.sendRedirect(request.getContextPath() + "/persona");
    return;
}
switch (action) {
    case "agregar":
        agregar(request, response);
        break;
    default:
        response.sendRedirect(request.getContextPath() + "/persona");
}

¿Qué pasa aquí?

  • Se establece UTF-8 para que los acentos lleguen bien
  • Según action, se deriva a agregar o por defecto a listar (aquí se usa un switch, pensando que más adelante se agregarán más acciones)

3.1) Agregar (alta)

private void agregar(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    int codigo = Integer.parseInt(request.getParameter("codigo"));
    String nombre = request.getParameter("nombre");
    dao.agregar(new PersonaVO(codigo, nombre));
    response.sendRedirect(request.getContextPath() + "/persona"); // PRG → listar
}

Flujo:

  1. Lee código y nombre del formulario de alta
  2. Crea el PersonaVO y lo agrega en el DAO
  3. Aplica PRG (Post/Redirect/Get) para volver al listado

4) Aplicar patrón PRG (Post → Redirect → Get)

Luego de cada operación POST se llama a:

response.sendRedirect(request.getContextPath() + "/persona"); // PRG → listar

¿Por qué?

  • Evita el reenvío del formulario si el usuario actualiza la página
  • Fuerza a que el navegador haga un GET al listado, lo que deja la UI en un estado consistente

Continuemos con MODELO- DAO/VO


📋 Palabras clave

PersonaControladorServlet · doGet · doPost · @WebServlet · action · getParameter · PRG · sendRedirect · forward · switch · PersonaDAO · PersonaVO · Controlador MVC


🧠 Autoevaluación — Mini-CRUD con MVC


← VISTA: Listar Personas · 🏠 Inicio · PersonaDAO y PersonaVO →