Modificaciones VISTA Alumnos - eliizquierdo/material_programacion_avanzada2026 GitHub Wiki

📦 Proyecto: mini-crud-alumno-sql (Tema 4 — Herencia + MySQL) — ⬇️ Descargar ZIP · ☁️ Abrir en Codespace

La capa Vista es responsable de la Presentación de la información y de la Interacción con el usuario, enviando peticiones al AlumnoControladorServlet.

Ahora en vez de persona-form.jsp, persona-editar.jsp y persona-lista.jsp vamos a tener analogamente alumno-form.jsp, alumno-editar.jsp y alumno-lista.jsp

1. Página de Inicio: index.jsp

indexAlumnos

Esta página es la puerta de entrada, mostrando las opciones principales.

Elemento Propósito URL Generada
Directiva @page Configura la codificación a UTF-8. N/A
${pageContext.request.contextPath} Expression Language (EL) para construir rutas relativas seguras. /mini-crud-alumno-sql (Ejemplo)
Botón "Agregar Alumnos" Muestra el formulario vacío para dar de alta un alumno. alumno?action=agregar
Botón "Listar Alumno" Muestra la tabla con todos los alumnos. alumno?action=listar (o /alumno por defecto)

🔑 Clave de la Vista: Se usa href="alumno?action=..." para invocar al AlumnoControladorServlet y delegarle la lógica de navegación o datos.

Veamos el código:

<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>CRUD con herencia</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/styles.css" />
  </head>
  <body>
    <div class="form-container">
      <h1>Bienvenidos al CRUD de alumnos</h1>

      <a class="btn" href="${pageContext.request.contextPath}/alumno?action=agregar"
        >Agregar Alumnos</a
      >
      <a class="btn" href="${pageContext.request.contextPath}/alumno?action=listar"
        >Listar Alumno</a
      >
    </div>
  </body>
</html>

2. Página Agregar Alumno: alumno-form.jsp

agregarAlumno

Esta página presenta el formulario para crear un nuevo alumno. Al igual que en persona-form.jsp, incluye manejo de errores con JSTL (por si el código ya existe).

Flujo de Llegada

El AlumnoControladorServlet recibe action=agregar (GET) y hace forward a esta vista.

📝 Formulario y Envío

Componente Código Clave Propósito
Acción del Formulario <form action="${pageContext.request.contextPath}/alumno" method="post"> POST al AlumnoControladorServlet. Esto dispara el doPost().
Campo Oculto <input type="hidden" name="action" value="agregar"> Le dice al doPost() del Servlet que debe ejecutar el método agregar().
Mensaje de error <c:if test="${requestScope.error != null}"> Muestra el error si el código ya existe (validación de unicidad, igual que en Persona).
Campos de Entrada name="codigo", name="nombre" y name="telefono" Capturan los datos del nuevo alumno. El código se ingresa a mano, igual que en el resto del curso (no es autoincremental).
Botón Guardar <button type="submit">Guardar</button> Envía la petición POST. El Servlet valida, procesa el alta y aplica el PRG.
Botón Volver <a href="${pageContext.request.contextPath}/alumno">Volver</a> Hace un GET simple a /alumno para volver al listado.

Veamos el código:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Agregar Alumno</title>
    <link
      rel="stylesheet"
      href="${pageContext.request.contextPath}/css/styles.css"
    />
  </head>
  <body>
    <div class="form-container">
      <h1>Agregar Alumno</h1>

      <c:if test="${requestScope.error != null}">
        <div
          style="
            color: red;
            border: 1px solid red;
            padding: 10px;
            margin-bottom: 15px;
            background-color: #ffe8e8;
          "
        >
          <strong>Error:</strong> ${requestScope.error}
        </div>
      </c:if>

      <form action="${pageContext.request.contextPath}/alumno" method="post">
        <input type="hidden" name="action" value="agregar" />

        <label>Código</label>
        <input type="number" name="codigo" required value="${requestScope.alumno.codigo}" />

        <label>Nombre</label>
        <input type="text" name="nombre" required value="${requestScope.alumno.nombre}" />

        <label>Teléfono</label>
        <input type="text" name="telefono" required value="${requestScope.alumno.telefono}" />

        <button class="btn" type="submit">Guardar</button>
        <a
          class="btn btn-secondary"
          href="${pageContext.request.contextPath}/alumno"
          >Volver</a
        >
      </form>
    </div>
  </body>
</html>

3. Página Listado de Alumnos: alumno-lista.jsp

listaAlumnos

Esta es la vista central que muestra los datos y las acciones de manipulación.

Flujo de Datos

  1. El Servlet recupera la lista: List<AlumnoVO> listaAlumnos = dao.listarAlumnos();
  2. Guarda la lista en la solicitud: request.setAttribute("alumnos", listaAlumnos);
  3. El JSP recorre la lista con JSTL: <c:forEach var="a" items="${requestScope.alumnos}">

📊 Iteración y Acciones

El cuerpo de la tabla (<tbody>) itera sobre alumnos usando JSTL, sin código Java embebido:

<c:if test="${not empty requestScope.alumnos}">
  <c:forEach var="a" items="${requestScope.alumnos}">
    <tr>
        <td>${a.codigo}</td>
        <td>${a.nombre}</td>
        <td>${a.telefono}</td>
        <td class="actions">
            <a href="${pageContext.request.contextPath}/alumno?action=editar&id=${a.codigo}">Editar</a>
            <form action="${pageContext.request.contextPath}/alumno" method="post" style="display:inline;">
                <input type="hidden" name="action" value="eliminar" />
                <input type="hidden" name="id" value="${a.codigo}" />
                <button type="submit" onclick="...">Eliminar</button>
            </form>
        </td>
    </tr>
  </c:forEach>
</c:if>
Acción Tipo de Petición Parámetros Clave Flujo
Editar GET action=editar&id=8 Invoca a doGet() para que ejecute mostrarEditar(), buscando el alumno 8.
Eliminar POST action=eliminar e id=8 (campos ocultos) Formulario con confirm(). Invoca a doPost() para que ejecute eliminar(). Luego aplica PRG.
Agregar Alumno GET action=agregar Vuelve a llamar al Servlet para mostrar alumno-form.jsp.

Veamos el código:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Listado de Alumnos</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/styles.css" />
  </head>
  <body>
    <div class="page-container">
      <h1>Listado de Alumnos</h1>

      <div class="table-wrap">
        <table class="table">
          <thead>
            <tr>
              <th>Código</th>
              <th>Nombre</th>
              <th>Teléfono</th>
              <th>Acciones</th>
            </tr>
          </thead>
          <tbody>
            <c:if test="${not empty requestScope.alumnos}">
              <c:forEach var="a" items="${requestScope.alumnos}">
                <tr>
                  <td>${a.codigo}</td>
                  <td>${a.nombre}</td>
                  <td>${a.telefono}</td>
                  <td class="actions">
                    <a
                      class="btn btn-edit"
                      href="${pageContext.request.contextPath}/alumno?action=editar&id=${a.codigo}"
                      >Editar</a
                    >
                    <form
                      action="${pageContext.request.contextPath}/alumno"
                      method="post"
                      style="display: inline"
                    >
                      <input type="hidden" name="action" value="eliminar" />
                      <input type="hidden" name="id" value="${a.codigo}" />
                      <button
                        type="submit"
                        class="btn btn-danger"
                        onclick="return confirm('¿Eliminar alumno?');"
                      >
                        Eliminar
                      </button>
                    </form>
                  </td>
                </tr>
              </c:forEach>
            </c:if>
            <c:if test="${empty requestScope.alumnos}">
              <tr>
                <td colspan="4">No hay alumnos cargados.</td>
              </tr>
            </c:if>
          </tbody>
        </table>
      </div>

      <a class="btn" href="${pageContext.request.contextPath}/alumno?action=agregar"
        >Agregar Alumno</a
      >
    </div>
  </body>
</html>

4. Página Editar Alumno: alumno-editar.jsp

editarAlumno

Esta nueva vista es crucial y es donde se ven los datos cargados previamente.

Flujo de Llegada

  1. El usuario selecciona Editar en alumno-lista.jsp.
  2. El Servlet recibe action=editar&id=X.
  3. El método mostrarEditar() busca el AlumnoVO y lo guarda como atributo: request.setAttribute("alumno", alumnoEncontrado);.
  4. El Servlet hace forward a alumno-editar.jsp.

⚙️ Carga de Datos y Envío

  • Carga de datos: El JSP usa Expression Language (EL) para precargar los valores en los campos de entrada:

    <input type="text" name="nombre" value="${requestScope.alumno.nombre}">
  • Acción Oculta: La acción del formulario se cambia a:

    <input type="hidden" name="action" value="actualizar">
  • Campo codigo: Se marca como readonly para que el usuario no lo altere (pero sigue viajando en el formulario para que el Servlet sepa qué registro modificar).

    <input type="number" name="codigo" value="${requestScope.alumno.codigo}" readonly>
  • Botón Actualizar: Dispara el POST con action=actualizar. El Servlet ejecuta actualizar(), que aplica la lógica de UPDATE y luego aplica el PRG.

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Editar Alumno</title>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/styles.css" />
  </head>
  <body>
    <div class="form-container">
      <h1>Editar Alumno</h1>

      <c:if test="${requestScope.alumno == null}">
        <div class="alert danger">No se encontró el alumno a editar.</div>
        <a class="btn btn-secondary" href="${pageContext.request.contextPath}/alumno">Volver</a>
      </c:if>
      <c:if test="${requestScope.alumno != null}">
        <!-- POST al Servlet con action=actualizar -->
        <form action="${pageContext.request.contextPath}/alumno" method="post">
          <input type="hidden" name="action" value="actualizar" />

          <label>Código</label>
          <input
            type="number"
            name="codigo"
            value="${requestScope.alumno.codigo}"
            readonly
          />

          <label>Nombre</label>
          <input
            type="text"
            name="nombre"
            value="${requestScope.alumno.nombre}"
            required
          />

          <label>Teléfono</label>
          <input
            type="text"
            name="telefono"
            value="${requestScope.alumno.telefono}"
            required
          />

          <button class="btn" type="submit">Actualizar</button>
          <a class="btn btn-secondary" href="${pageContext.request.contextPath}/alumno">Volver</a>
        </form>
      </c:if>
    </div>
  </body>
</html>

Ahora que la capa Vista está clara, podemos proceder a analizar cómo el AlumnoControladorServlet gestiona estas peticiones (que ya hicimos en la respuesta anterior, pero enfocaremos los cambios clave si fuera necesario).

Continuemos con el Resumen


📋 Palabras clave

alumno-form.jsp · alumno-lista.jsp · alumno-editar.jsp · Vista MVC · JSP · teléfono · AlumnoVO · Expression Language · EL · JSTL · c:forEach · c:if · precarga de datos · tabla · formulario


🧠 Autoevaluación — Herencia en Java y BD


← AlumnoControladorServlet · 🏠 Inicio · Resumen Tema 4 →

⚠️ **GitHub.com Fallback** ⚠️