Servlets y JSP: tutorial Jakarta EE 10 y Java 21

El patrón de arquitectura recomendado para aplicaciones Jakarta EE sin framework es el MVC Front Controller: un único Servlet recibe todas las peticiones, procesa la lógica y delega la presentación a JSPs.

Petición HTTP → Servlet (Controlador) → Servicio (Modelo) → JSP (Vista)

Ejemplo completo: lista de productos

// Modelo: entidad y servicio
record Producto(int id, String nombre, double precio) {}

public class ProductoService {
    private static final List<Producto> DB = List.of(
        new Producto(1, "Teclado mecánico", 89.99),
        new Producto(2, "Ratón gaming",     49.95),
        new Producto(3, "Monitor 27\"",    349.00)
    );
    public List<Producto> findAll() { return DB; }
    public Producto findById(int id) {
        return DB.stream().filter(p -> p.id() == id).findFirst().orElse(null);
    }
}
// Controlador: ProductoServlet.java
@WebServlet("/productos/*")
public class ProductoServlet extends HttpServlet {

    private final ProductoService service = new ProductoService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        String pathInfo = req.getPathInfo(); // null o "/123"

        if (pathInfo == null || pathInfo.equals("/")) {
            // Listar todos
            req.setAttribute("productos", service.findAll());
            req.getRequestDispatcher("/WEB-INF/views/lista.jsp")
               .forward(req, resp);
        } else {
            // Detalle de uno
            int id = Integer.parseInt(pathInfo.substring(1));
            Producto p = service.findById(id);
            if (p == null) {
                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            req.setAttribute("producto", p);
            req.getRequestDispatcher("/WEB-INF/views/detalle.jsp")
               .forward(req, resp);
        }
    }
}
<!-- /WEB-INF/views/lista.jsp -->
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<!DOCTYPE html>
<html><head><title>Productos</title></head>
<body>
<h1>Catálogo de productos</h1>
<table>
  <thead><tr><th>Nombre</th><th>Precio</th></tr></thead>
  <tbody>
    <c:forEach items="${productos}" var="p">
      <tr>
        <td><a href="productos/${p.id}"><c:out value="${p.nombre}"/></a></td>
        <td><fmt:formatNumber value="${p.precio}" type="currency" currencySymbol="€"/></td>
      </tr>
    </c:forEach>
  </tbody>
</table>
</body></html>

Forward vs Redirect

// Forward: el Servlet delega a otro recurso SIN cambiar la URL del navegador
// Los atributos de request (setAttribute) se mantienen
req.getRequestDispatcher("/WEB-INF/views/lista.jsp").forward(req, resp);

// Redirect: envía 302 al navegador para que haga una nueva petición
// La URL del navegador cambia; los atributos de request se pierden
// Se usa para el patrón Post-Redirect-Get (PRG): después de un POST exitoso
resp.sendRedirect(req.getContextPath() + "/productos");

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR