Tecnología JSP (JavaServer Pages)

📅 Actualizado en febrero 2026 ✍️ Ángel López ⏱️ 18 min de lectura ✓ Nivel intermedio
🚨
Estado actual de esta tecnología: JSP se considera una tecnología legacy (heredada). Aunque sigue funcionando en servidores modernos como Tomcat 10, la comunidad Java ha migrado hacia alternativas como Thymeleaf, APIs REST con Spring Boot o frontends SPA con React/Angular/Vue. Este artículo cubre JSP con rigor técnico porque sigue siendo relevante para mantener aplicaciones existentes, entender la base conceptual de las tecnologías web Java actuales, y certificaciones y entrevistas. La sección final detalla las alternativas recomendadas.

JavaServer Pages (JSP) es una tecnología del ecosistema Java que permite crear páginas web dinámicas mezclando HTML estático con código Java embebido. Fue la solución estándar de la capa de presentación en aplicaciones Java EE durante más de una década, y su comprensión sigue siendo esencial para cualquier desarrollador Java que trabaje con aplicaciones empresariales.

En esta guía aprenderemos qué es JSP, cómo funciona internamente (ciclo de vida), su sintaxis completa (scriptlets, expresiones, directivas, acciones y Expression Language), los objetos implícitos disponibles y, muy importante, por qué la industria ha evolucionado hacia enfoques diferentes y cuáles son las alternativas modernas recomendadas.

📋 Tabla resumen: elementos de JSP

ElementoSintaxisDescripción
Scriptlet<% código %>Bloque de código Java ejecutado en el servidor
Expresión<%= expr %>Evalúa la expresión y escribe el resultado en el HTML
Declaración<%! decl %>Declara métodos o variables a nivel de clase del servlet
Directiva page<%@ page ... %>Configura encoding, imports, página de error, sesión
Directiva include<%@ include ... %>Incluye un fichero en tiempo de compilación
Directiva taglib<%@ taglib ... %>Importa biblioteca de etiquetas (ej. JSTL)
Acción include<jsp:include />Incluye un recurso en tiempo de ejecución
Acción forward<jsp:forward />Redirige la petición a otro recurso
Acción useBean<jsp:useBean />Instancia o recupera un JavaBean del scope
Expression Language${expresión}Accede a datos sin código Java (JSP 2.0+)
Comentario JSP<%-- texto --%>Comentario del servidor, invisible en el HTML

🔄 Ciclo de vida de una página JSP

Cuando un navegador solicita una página .jsp por primera vez, el servidor ejecuta tres fases:

1. Traducción: El motor JSP convierte el archivo .jsp en un .java que es un servlet completo. El HTML estático se convierte en sentencias out.write() y el código Java embebido se copia al método _jspService().

2. Compilación: El .java generado se compila a bytecode (.class).

3. Ejecución: El servlet compilado se carga en memoria y atiende la petición. Las peticiones siguientes reutilizan el servlet ya compilado, salvo que el archivo .jsp sea modificado.

💡
Concepto clave: Una página JSP es un servlet. El motor JSP automatiza la conversión de «HTML con Java embebido» a un servlet que genera ese HTML programáticamente. Esta equivalencia es fundamental para entender las tecnologías web Java.

💻 Elementos de scripting: scriptlets, expresiones y declaraciones

✍️ Scriptlets: <% ... %>

Un scriptlet es un bloque de código Java insertado directamente en el método _jspService() del servlet generado:

JSP — Scriptlet con bucle
<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
    <h1>Lista de productos</h1>
    <ul>
    <%
        String[] productos = {"Portátil", "Monitor", "Teclado"};
        for (String p : productos) {
    %>
        <li><%= p %></li>
    <%  }  %>
    </ul>
</body></html>

💬 Expresiones: <%= ... %>

Una expresión JSP evalúa una expresión Java y escribe su resultado en la salida HTML. No lleva punto y coma:

JSP — Expresiones
<p>Fecha actual: <%= new java.util.Date() %></p>
<p>Tu navegador: <%= request.getHeader("User-Agent") %></p>
<p>Parámetro: <%= request.getParameter("nombre") %></p>

📜 Declaraciones: <%! ... %>

Las declaraciones definen métodos y variables a nivel de clase del servlet generado (fuera de _jspService()):

JSP — Declaración de método y variable
<%!
    private int contador = 0;

    private String formatear(int n) {
        return String.format("%,d", n);
    }
%>
<% contador++; %>
<p>Visitas: <%= formatear(contador) %></p>
⚠️
Cuidado con la concurrencia: Las variables declaradas con <%! %> son compartidas entre todos los hilos. El contador del ejemplo es no thread-safe. En código real, este tipo de estado compartido debe evitarse o protegerse con sincronización.

📝 Directivas JSP

Las directivas no producen salida HTML, sino que configuran cómo el motor traduce y compila la página:

JSP — Las tres directivas principales
<%-- Directiva page: configuración general --%>
<%@ page language="java"
    contentType="text/html;charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.List, java.util.ArrayList"
    errorPage="error.jsp"
    session="true" %>

<%-- Directiva include: inclusión estática en compilación --%>
<%@ include file="cabecera.jsp" %>

<%-- Directiva taglib: importar JSTL --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

⚙️ Acciones estándar JSP

Las acciones estándar son etiquetas XML que el contenedor JSP interpreta en tiempo de ejecución. A diferencia de las directivas (que actúan en compilación), las acciones se evalúan en cada petición:

JSP — Acciones estándar más utilizadas
<%-- Inclusión dinámica: se ejecuta en cada petición --%>
<jsp:include page="menu.jsp" />

<%-- Reenvío interno: el cliente no ve el cambio de URL --%>
<jsp:forward page="resultado.jsp">
    <jsp:param name="mensaje" value="Operación completada" />
</jsp:forward>

<%-- useBean: instancia o recupera un JavaBean --%>
<jsp:useBean id="usuario" class="com.empresa.Usuario" scope="session" />
<jsp:setProperty name="usuario" property="nombre" value="Ana" />
<p>Nombre: <jsp:getProperty name="usuario" property="nombre" /></p>

La diferencia entre <%@ include %> (directiva) y <jsp:include> (acción) es esencial. La directiva copia el fichero en tiempo de compilación, generando un único servlet. La acción ejecuta el recurso incluido como una petición separada, lo que permite incluir contenido dinámico que cambia independientemente del fichero principal.

Patrón MVC con JSP: En la arquitectura Model-View-Controller, el Servlet actúa como controlador (recibe la petición, procesa la lógica, coloca datos en el request), el JavaBean es el modelo (datos), y la JSP es la vista (presenta los datos con HTML). La acción <jsp:forward> permite al Servlet redirigir la petición a la JSP correspondiente.

🔍 Los cuatro scopes de JSP

Uno de los conceptos más importantes de JSP (y de todas las tecnologías web Java posteriores) son los cuatro ámbitos (scopes) donde se pueden almacenar y recuperar datos:

ScopeDuraciónAccesible desdeUso típico
pageSolo la página actualLa propia JSPVariables temporales de la página
requestUna petición HTTP completaServlet + JSPs incluidas/forwardPasar datos del Servlet a la JSP (patrón MVC)
sessionToda la sesión del usuarioCualquier página del mismo usuarioLogin, carrito de compras, preferencias
applicationToda la vida de la aplicaciónCualquier página de cualquier usuarioConfiguración global, contadores
JSP — Acceso a scopes con Expression Language
<%-- Acceso explícito a cada scope con EL --%>
<p>Variable de página: ${pageScope.temporal}</p>
<p>Dato del request: ${requestScope.listaProductos}</p>
<p>Usuario en sesión: ${sessionScope.usuario.nombre}</p>
<p>Config global: ${applicationScope.version}</p>

<%-- EL busca automáticamente en page → request → session → application --%>
<p>Búsqueda automática: ${miVariable}</p>

Entender los scopes es fundamental porque este mismo concepto se aplica en Spring MVC (Model, @SessionAttributes), en JSF (@RequestScoped, @SessionScoped) y en prácticamente cualquier framework web Java. Quien domina los scopes de JSP tiene una base sólida para cualquier tecnología posterior.

📦 Objetos implícitos de JSP

Dentro de cualquier página JSP hay nueve objetos predefinidos creados automáticamente por el motor:

ObjetoTipo JavaDescripción
requestHttpServletRequestPetición HTTP (parámetros, cabeceras, cookies)
responseHttpServletResponseRespuesta HTTP al cliente
outJspWriterFlujo de salida para escribir HTML
sessionHttpSessionSesión del usuario entre peticiones
applicationServletContextContexto global de la aplicación
configServletConfigConfiguración del servlet
pageContextPageContextAcceso a todos los scopes y atributos
pageObject (this)Referencia al servlet actual
exceptionThrowableExcepción capturada (solo en páginas de error)

💡 Expression Language (EL): la evolución de JSP

Desde JSP 2.0 (año 2003), el Expression Language (EL) permite acceder a datos sin escribir código Java, usando la sintaxis ${expresión}:

JSP — Scriptlet vs. Expression Language
<%-- Antes (scriptlet) - NO RECOMENDADO --%>
<p>Hola, <%= request.getParameter("nombre") %></p>

<%-- Después (EL) - RECOMENDADO --%>
<p>Hola, ${param.nombre}</p>

<%-- Acceso a un JavaBean en sesión --%>
<p>Bienvenido, ${sessionScope.usuario.nombre}</p>

<%-- Operadores en EL --%>
<p>Precio con IVA: ${producto.precio * 1.21}</p>
<p>¿Carrito vacío? ${empty carrito.items}</p>
🎓
Buena práctica: Desde 2003, la recomendación oficial es eliminar todos los scriptlets y usar exclusivamente EL + JSTL. Los scriptlets se mantienen por compatibilidad, pero están considerados mala práctica desde hace más de 20 años.

🎯 Ejemplo integrador: catálogo de productos con JSTL + EL

Una página JSP moderna (sin scriptlets) que muestra un catálogo de productos recibido desde un Servlet controlador:

JSP — Catálogo con JSTL + EL (sin scriptlets)
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html><head><title>Catálogo</title></head>
<body>
    <h1>Nuestros Productos</h1>
    <c:if test="${not empty sessionScope.usuario}">
        <p>Hola, ${sessionScope.usuario.nombre}</p>
    </c:if>

    <c:choose>
        <c:when test="${empty productos}">
            <p>No hay productos disponibles.</p>
        </c:when>
        <c:otherwise>
            <table border="1">
            <tr><th>Nombre</th><th>Precio</th><th>Stock</th></tr>
            <c:forEach var="p" items="${productos}">
                <tr>
                    <td>${p.nombre}</td>
                    <td><fmt:formatNumber value="${p.precio}" type="currency"
                         currencySymbol="€"/></td>
                    <td>${p.stock > 0 ? 'Disponible' : 'Agotado'}</td>
                </tr>
            </c:forEach>
            </table>
        </c:otherwise>
    </c:choose>
</body></html>

Observa que no hay ni una línea de código Java directo. La iteración y condiciones se gestionan con JSTL (c:forEach, c:if, c:choose) y el acceso a datos con EL (${...}). Los datos los carga un Servlet controlador que los coloca en el request antes de redirigir a esta JSP.

🚨 Estado actual: ¿por qué JSP se considera legacy?

JSP fue revolucionaria en su momento (1999-2010), pero la industria ha evolucionado significativamente:

❌ Acoplamiento lógica/presentación: Aunque EL+JSTL mejoraron la situación, la tentación de usar scriptlets siempre existió. Miles de aplicaciones reales tienen páginas JSP con código Java mezclado con HTML, creando código difícil de mantener.

❌ Imposibilidad de previsualizar: Los archivos .jsp no se pueden abrir en un navegador sin un servidor de aplicaciones, dificultando el trabajo de diseñadores web.

❌ Separación front/back: La arquitectura moderna separa el backend (API REST) del frontend (SPA). JSP fuerza un modelo «server-side rendering» monolítico que no se adapta a esta separación.

❌ Testing complejo: Probar una JSP requiere levantar un contenedor de servlets. Las alternativas modernas permiten tests unitarios sin infraestructura.

✅ Alternativas modernas recomendadas

TecnologíaTipoVentaja principalCuándo elegirla
ThymeleafMotor de plantillasHTML natural previsualizableApps MVC con Spring Boot
Spring Boot + REST + React/VueAPI + SPASeparación total front/backProyectos nuevos, equipos grandes
JSF con FaceletsComponentesParte de Jakarta EEEntornos estrictamente Jakarta EE
VaadinFull-stack JavaUI desde Java, sin JS/HTMLApps internas de empresa
HTMX + SpringHipermedia modernaInteractividad sin SPASimplicidad con interactividad
💡
¿Cuándo sigue siendo relevante conocer JSP? Para mantener aplicaciones empresariales existentes (miles en producción), para entender los conceptos base de las tecnologías web Java actuales (scopes, request/response, sesiones, EL), y para certificaciones Oracle Java EE o entrevistas técnicas.

⚠️ Errores frecuentes al trabajar con JSP

Error 1: Usar scriptlets en proyectos nuevos. Desde 2003 la recomendación es evitar los scriptlets (<% %>) y usar EL + JSTL. Si escribes código Java dentro de una JSP en un proyecto nuevo, la arquitectura es incorrecta.
Error 2: Poner lógica de negocio en la JSP. La JSP es la vista del patrón MVC. Solo debe mostrar datos. Las consultas a base de datos, cálculos o validaciones deben estar en clases Java, nunca en la JSP.
Error 3: Olvidar el encoding UTF-8. Sin pageEncoding="UTF-8" en la directiva page, los caracteres especiales (acentos, eñes) se muestran como caracteres ilegibles. Siempre configura contentType y pageEncoding como UTF-8.
Error 4: Confundir inclusión estática y dinámica. <%@ include file="..." %> copia el contenido en tiempo de compilación (estática). <jsp:include page="..." /> incluye en tiempo de ejecución (dinámica). Si el fichero incluido cambia con frecuencia, usa la inclusión dinámica.

✏️ Ejercicios prácticos

📝 Ejercicio 1: Formulario y procesamiento con JSP + EL

Crea dos páginas: formulario.jsp con un formulario HTML que pida nombre y edad, y resultado.jsp que muestre los datos recibidos usando Expression Language (${param.nombre} y ${param.edad}). No uses scriptlets.

formulario.jsp + resultado.jsp
<%-- formulario.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
    <h2>Registro</h2>
    <form action="resultado.jsp" method="post">
        Nombre: <input type="text" name="nombre"/><br/>
        Edad: <input type="number" name="edad"/><br/>
        <button type="submit">Enviar</button>
    </form>
</body></html>

<%-- resultado.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" %>
<html><body>
    <h2>Datos recibidos</h2>
    <p>Nombre: ${param.nombre}</p>
    <p>Edad: ${param.edad}</p>
    <p>Mayor de edad: ${param.edad >= 18 ? 'Sí' : 'No'}</p>
</body></html>

📝 Ejercicio 2: Tabla dinámica con JSTL

Crea una página JSP que use <c:forEach> de JSTL para mostrar una tabla HTML con los números del 1 al 10, su cuadrado y su cubo. No uses scriptlets.

JSP — Tabla de potencias con JSTL
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html><body>
    <h2>Tabla de potencias</h2>
    <table border="1">
        <tr><th>N</th><th>N²</th><th>N³</th></tr>
        <c:forEach var="n" begin="1" end="10">
            <tr>
                <td>${n}</td>
                <td>${n * n}</td>
                <td>${n * n * n}</td>
            </tr>
        </c:forEach>
    </table>
</body></html>

📝 Ejercicio 3: Página de error personalizada

Crea una página error.jsp que se active como página de error y muestre el tipo de excepción y su mensaje usando el objeto implícito exception. Configura otra página para que use esta página de error con la directiva errorPage.

error.jsp + pagina_que_falla.jsp
<%-- error.jsp - Página de error --%>
<%@ page contentType="text/html;charset=UTF-8"
    isErrorPage="true" %>
<html><body>
    <h1 style="color:red">Error en la aplicación</h1>
    <p>Tipo: ${pageContext.exception.class.name}</p>
    <p>Mensaje: ${pageContext.exception.message}</p>
    <a href="index.jsp">Volver al inicio</a>
</body></html>

<%-- pagina_que_falla.jsp --%>
<%@ page contentType="text/html;charset=UTF-8"
    errorPage="error.jsp" %>
<html><body>
    <%
        // Esto provoca una excepción para demostrar
        int resultado = 10 / 0;
    %>
</body></html>

❓ Preguntas frecuentes sobre Tecnología JSP (JavaServer Pages)

Las dudas más comunes respondidas de forma clara y directa.

JSP (JavaServer Pages) es una tecnología del ecosistema Java EE que permite crear páginas web dinámicas mezclando HTML estático con código Java embebido. Las páginas .jsp se compilan automáticamente en servlets la primera vez que se solicitan. Fue la tecnología estándar de presentación web en Java durante los años 2000-2015.
JSP se considera una tecnología legacy (heredada). Aunque sigue siendo parte de la especificación Jakarta EE y funciona en servidores modernos como Tomcat 10, la comunidad Java ha migrado hacia alternativas como Thymeleaf, APIs REST con Spring Boot, o frontends SPA con React, Angular o Vue. Los nuevos proyectos raramente eligen JSP, pero existe una enorme base de código legacy que lo utiliza.
Un Servlet es una clase Java pura que procesa peticiones HTTP y genera respuestas programáticamente. Una página JSP es un documento con apariencia de HTML que contiene fragmentos de código Java. Internamente, el servidor convierte cada JSP en un Servlet antes de ejecutarlo. Los Servlets son «Java con HTML embebido» y las JSP son «HTML con Java embebido».
Las alternativas modernas más populares son: Thymeleaf (motor de plantillas con HTML natural, integrado con Spring Boot), APIs REST + frontend SPA (Spring Boot devuelve JSON, el frontend se construye con React, Angular o Vue), JSF con Facelets (parte de Jakarta EE), y Vaadin (framework Java que genera la UI desde el servidor sin escribir HTML).
Conocer JSP es importante por tres razones: existe una enorme cantidad de aplicaciones empresariales en producción que todavía usan JSP y necesitan mantenimiento; los conceptos de JSP (ciclo request-response, sesiones, scopes, EL) son la base de todas las tecnologías web Java posteriores; y muchos exámenes de certificación Java y entrevistas técnicas siguen incluyendo preguntas sobre JSP.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Tecnología JSP (JavaServer Pages)? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!