Introducción
Anteriormente, al trabajar con Servlets, la generación de páginas web se realizaba a través de respuestas del servidor. Este enfoque presentaba varias limitaciones:
- Dificultad en el desarrollo: Requería heredar de clases base, sobrescribir métodos y configurar
web.xmlo anotaciones. - Complejidad en las modificaciones: Cualquier cambio implicaba recompilar, desplegar y reiniciar el servidor.
- Elaboración de la visualización: Implicaba obtener flujos de salida y usar
println()para imprimir cada línea, resultando en código poco legible. - Colaboración complicada: Los diseñadores de UI se centraban en la estética y los desarrolladores en la lógica Java, pero la comunicación y la integración de ambos aspectos era difícil.
JSP (JavaServer Pages)
JSP es una tecnología que simplifica el desarrollo de Servlets. Permite incrustar código Java directamente dentro de etiquetas HTML para crear páginas web dinámicas de manera eficiente.
- Propósito: Sustituye la parte de visualización de un Servlet. Un archivo
.jspreemplaza a un archivoXxxJSP.java.
Desarrollo con JSP (Énfasis Principal)
Creación de un JSP
Para crear un archivo JSP, simplemente se genera un archivo *.jsp dentro del directorio web, al mismo nivel que WEB-INF.
Incrustación de Código Java en JSP
El código Java se puede integrar en el HTML utilizando etiquetas especiales.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Mi Primera Página JSP</title>
</head>
<body>
La hora actual es: <%= new java.util.Date() %>
</body>
</html>
La etiqueta <%= ... %> se utiliza para insertar la expresión Java directamente en la página, mostrando la fecha y hora del sistema actual.
Acceso a un JSP
Para acceder a una página JSP, se utiliza la siguiente estructura en el navegador: http://ip:puerto/ruta_del_proyecto/nombre_del_recurso.
JSP y Servlets
- Relación: Un archivo JSP se traduce a un Servlet dentro del contenedor web y se ejecuta como tal. En esencia, JSP es una abstracción de alto nivel sobre Servlets.
- Diferencias: JSP facilita enormemente la creación y modificación de páginas HTML en comparación con la gestión de múltiples sentencias
println()en Servlets.- Servlet: Requiere heredar de
HttpServlet, configuración (web.xmlo anotaciones), recompilación, despliegue y reinicio del servidor para cambios. El código HTML se imprime línea por línea. - JSP: Permite escribir código Java directamente en el HTML. Las modificaciones se reflejan simplemente refrescando la página en el navegador.
- Servlet: Requiere heredar de
Principio de Funcionamiento de JSP
Cuando se solicita un archivo .jsp, el servidor web (como Tomcat) lo convierte en código Java, lo compila a un archivo .class y luego lo ejecuta. El resultado de esta ejecución se envía como respuesta al cliente.
Ubicación de los Archivos Generados por JSP
En entornos de desarrollo como IntelliJ IDEA con Tomcat, los archivos Java y .class generados a partir de los JSPs se encuentran típicamente en:
C:\Usuarios\<nombre_usuario>\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\<nombre_proyecto>\work\Catalina\localhost\<contexto_aplicacion>\org\apache\jsp</contexto_aplicacion></nombre_proyecto></nombre_usuario>
(AppData puede ser una carpeta oculta).
Desarrollo Integrado de JSP y HTML
Scripts
Los scripts permiten la inclusión de sentencias, variables, métodos y expresiones Java dentro de un JSP.
Script Ordinario
Sintaxis: <% Java code %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Uso de Scripts</title>
</head>
<body>
<%
// En JSP, los scripts ordinarios permiten incrustar código Java.
int a = 10; // Define una variable local.
System.out.println(a); // Imprime en la consola del servidor.
out.println(a); // Imprime en la página del cliente.
%>
</body>
</html>
Nota: Los scripts ordinarios admiten toda la sintaxis Java excepto la definición de funciones. Los scripts no pueden anidarse entre sí ni con etiquetas HTML.
Script de Declaración
Sintaxis: <%! Variable declaration, Method declaration %>
<%!
int b = 20; // Define una variable global.
public void test() { // Define un método sin valor de retorno.
System.out.println("Hola");
}
public int test1() { // Define un método con valor de retorno.
return 100;
}
%>
Nota: Las variables declaradas en este script son globales. Los métodos declarados aquí deben ser llamados desde un script ordinario o de expresión. Si un método tiene un valor de retorno, se puede invocar usando un script de expresión.
Script de Expresión
Sintaxis: <%= Java expression %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Uso de Scripts de Expresión</title>
</head>
<body>
<%= test1() %> <br></br>
<%= "¡Hoy hace buen tiempo!" %> <br></br>
<%= 666 %> <br></br>
<%= new Date() %> <br></br>
</body>
</html>
Nota: Los scripts de expresión pueden llamar a funciones con valor de retorno. No deben incluir punto y coma al final.
Comentarios JSP
Los comentarios en JSP tienen dos propósitos:
<%-- Comentario JSP --%>: Este comentario no se envía al navegador ni se compila.<!-- Comentario HTML -->: Este comentario se puede ver en el código fuente de la página web en el navegador.
<%-- Este comentario JSP no se mostrará en la página --%>
<!-- Este comentario HTML se mostrará en el código fuente -->
Directivas JSP
Las directivas configuran atributos relacionados con la página JSP completa.
<%@ page ... %>: Define atributos de la página, como el lenguaje de script, la página de error, la gestión de caché, etc.<%@ include ... %>: Incluye el contenido de otro archivo.<%@ taglib ... %>: Importa definiciones de bibliotecas de etiquetas.
Directiva page
Sintaxsi: <%@ page attribute1="value1" attribute2="value2" %>
Atributos comunes incluyen:
contentType: Define el tipo MIME y la codificación de caracteres de la página.errorPage: Especifica la página a la que se redirigirá si ocurre una excepción.isErrorPage: Indica si la página actual puede actuar como manejador de errores.import: Importa clases Java necesarias.language: Define el lenguaje de script (por defecto, Java).session: Determina si se usa la sesión (truepor defecto, crea sesión inmediatamente;false, crea al usarla).pageEncoding: Especifica la codificación de la página JSP.
Directiva include
Sintaxis: <%@ include file="ruta/al/archivo" %>
Incluye estáticamente el contenido de otro archivo (JSP, HTML, texto) en el momento de la compilación. El contenido incluido se trata como parte del archivo JSP actual.
<%@ include file="header.jsp" %>
...
<%@ include file="footer.jsp" %>
Precaución: Puede causar conflictos de nombres y no se recomienda su uso intensivo.
Directiva taglib
Sintaxis: <%@ taglib uri="ruta_biblioteca_etiquetas" prefix="prefijo" %>
Importa bibliotecas de etiquetas estándar o personalizadas.
<%@ taglib url="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Etiquetas de Acción
Sintaxis: <jsp:action_name attribute="value" />
Las etiquetas de acción son comandos que se ejecutan en tiempo de ejecución.
jsp:include
Sintaxis: <jsp:include page="URL_relativa" />
Realiza una inclusión dinámica, incorporando el resultado de la salida de otro recurso.
<jsp:include page="index.jsp" />
Diferencia con <%@ include %>: jsp:include inserta el contenido generado en tiempo de ejecución, mientras que la directiva include inserta el código fuente en tiempo de compilación.
jsp:useBean
Sintaxis: <jsp:useBean id="nombre" class="paquete.NombreClase" />
Carga un JavaBean para su uso en la página JSP.
<jsp:useBean id="usuario" class="com.ejemplo.modelo.Usuario" />
Las propiedades del bean se pueden modificar o acceder usando jsp:setProperty y jsp:getProperty.
jsp:setProperty
Establece el valor de una propiedad de un JavaBean.
Sintaxis: <jsp:setProperty name="nombreBean" property="nombrePropiedad" value="valor" />
<jsp:useBean id="usuario" class="com.ejemplo.modelo.Usuario" />
<jsp:setProperty name="usuario" property="nombre" value="Mundo" />
jsp:getProperty
Obtiene el valor de una propiedad de un JavaBean, lo convierte a cadena y lo imprime.
Sintaxis: <jsp:getProperty name="nombreBean" property="nombrePropiedad" />
<jsp:useBean id="usuario" class="com.ejemplo.modelo.Usuario" />
<jsp:setProperty name="usuario" property="nombre" value="Mundo" />
<jsp:getProperty name="usuario" property="nombre" />
jsp:forward
Sintaxis: <jsp:forward page="URL_relativa" />
Redirige la solicitud a otra página.
<jsp:forward page="otraPagina.jsp" />
jsp:param
Sintaxis: <jsp:param name="nombreParametro" value="valorParametro" />
Se utiliza dentro de otras etiquetas de acción (como jsp:include o jsp:forward) para pasar parámetros.
<jsp:forward page="procesar.jsp">
<jsp:param name="idUsuario" value="123" />
</jsp:forward>
Para obtener el parámetro en la página de destino: <%= request.getParameter("idUsuario") %>
Objetos Incorporados
JSP proporciona varios objetos predefinidos que se pueden usar directamente:
| Objeto | Tipo | Descripción |
|---|---|---|
request |
javax.servlet.http.HttpServletRequest |
Información sobre la solicitud del cliente. |
response |
javax.servlet.http.HttpServletResponse |
Para enviar respuestas al cliente. |
session |
javax.servlet.http.HttpSession |
Gestiona la información de la sesión del usuario (activado por session="true"). |
application |
javax.servlet.ServletContext |
Representa el contexto de la aplicación web. |
config |
javax.servlet.ServletConfig |
Configuración del Servlet. |
exception |
java.lang.Throwable |
Excepción ocurrida (disponible si isErrorPage="true"). |
out |
javax.servlet.jsp.JspWriter |
Para escribir en el flujo de salida de la respuesta. |
pageContext |
javax.servlet.jsp.PageContext |
Proporciona acceso a todos los demás objetos y gestiona los ámbitos. |
page |
java.lang.Object |
Referencia a la instancia del Servlet actual (this). |
Cuatro Ámbitos Principales
Los objetos de ámbito almacenan y recuperan datos con diferentes alcances:
pageContext: Ámbito de la página actual.request: Válido para una única solicitud.session: Válido para una única sesión de usuario (se pierde al cerrar el navegador).application: Válido para toda la aplicación web (se pierde al reiniciar el servidor).
Objeto pageContext
El objeto pageContext, una instancia de javax.servlet.jsp.PageContext, representa la página JSP completa y gestiona los ámbitos.
- Almacenar valores:
pageContext.setAttribute("nombre", valor); - Obtener valores:
pageContext.getAttribute("nombre"); - Permite acceder a los otros 8 objetos incorporados y gestionar sus ámbitos.
<%
pageContext.setAttribute("nombre", "valor"); // Válido solo en esta página.
%>
Obtener Otros Objetos Incorporados desde pageContext
<%
HttpServletRequest req = pageContext.getRequest();
HttpServletResponse res = pageContext.getResponse();
HttpSession ses = pageContext.getSession();
ServletContext app = pageContext.getServletContext();
JspWriter writer = pageContext.getOut();
Throwable ex = pageContext.getException();
Object pageObj = pageContext.getPage();
ServletConfig conf = pageContext.getServletConfig();
%>
Operaciones de Ámbito con pageContext
<%
/* Almacenar en otros ámbitos */
pageContext.setAttribute("paginaScope", "valorPagina", PageContext.PAGE_SCOPE);
pageContext.setAttribute("requestScope", "valorRequest", PageContext.REQUEST_SCOPE);
pageContext.setAttribute("sessionScope", "valorSession", PageContext.SESSION_SCOPE);
pageContext.setAttribute("applicationScope", "valorApplication", PageContext.APPLICATION_SCOPE);
/* Obtener desde otros ámbitos */
String valPagina = (String) pageContext.getAttribute("paginaScope", PageContext.PAGE_SCOPE);
String valRequest = (String) pageContext.getAttribute("requestScope", PageContext.REQUEST_SCOPE); // O usando request.getAttribute("requestScope")
String valSession = (String) pageContext.getAttribute("sessionScope", PageContext.SESSION_SCOPE); // O usando session.getAttribute("sessionScope")
String valApplication = (String) pageContext.getAttribute("applicationScope", PageContext.APPLICATION_SCOPE); // O usando application.getAttribute("applicationScope")
// Búsqueda en todos los ámbitos (page, request, session, application)
String valorEncontrado = (String) pageContext.findAttribute("requestScope");
%>
Integración
Reemplazo de Servlets por JSPs en el proyecto EmpProject para la visualización, utilizando scripts para mostrar datos.
showAllEmp.jsp
<%@ page import="com.dz.emp.entity.Emp" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Consulta de Todos los Empleados</title>
</head>
<body>
<form action='/EmpProject/manager/safe/showInsertEmp.jsp'>
<p><input type='submit' value='Nuevo'></p>
</form>
<table border='1'>
<tr>
<td>ID</td>
<td>Nombre</td>
<td>Salario</td>
<td>Edad</td>
<td colspan='2'>Acciones</td>
</tr>
<%
List<Emp> empList = (List<Emp>) request.getAttribute("empList");
if (empList != null) {
for (Emp emp : empList) {
%>
<tr>
<td><%=emp.getId()%></td>
<td><%=emp.getName()%></td>
<td><%=emp.getSalary()%></td>
<td><%=emp.getAge()%></td>
<td><a href="<%=request.getContextPath()+"/manager/safe/removeEmpController?id="+emp.getId()%>">Eliminar</a></td>
<td><a href="<%=request.getContextPath()+"/manager/safe/showEmpController?id="+emp.getId()%>">Modificar</a></td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
showInsertEmp.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Alta de Empleado</title>
</head>
<body>
<form action='/EmpProject/manager/safe/insertEmpController' method='post'>
<p>Nombre:<input type='text' name='name'></p>
<p>Salario:<input type='text' name='salary'></p>
<p>Edad:<input type='text' name='age'></p>
<p><input type='submit' value='Enviar'></p>
</form>
</body>
</html>
showUpdateEmp.jsp
<%@ page import="com.dz.emp.entity.Emp" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Modificar Información de Empleado</title>
</head>
<body>
<%
Emp emp = (Emp) request.getAttribute("emp");
%>
<form action='/EmpProject/manager/safe/updateEmpController' method='post'>
<p>ID:<input type='text' name='id' value=<%=emp.getId()%> readonly></p>
<p>Nombre:<input type='text' name='name' value=<%=emp.getName()%>></p>
<p>Salario:<input type='text' name='salary' value=<%=emp.getSalary()%>></p>
<p>Edad:<input type='text' name='age' value=<%=emp.getAge()%>></p>
<p><input type='submit' value='Actualizar'></p>
</form>
</body>
</html>
Expresión de Lenguaje (EL)
Concepto
EL (Expression Language) simplifica la escritura en JSP, permitiendo acceder a datos de los ámbitos de forma concisa.
Propósito
Reemplaza las llamadas a ambito.getAttribute("nombre").
Aplicación (Tipos Primitivos y Cadenas)
${ambito.nombre}: Accede a un dato de un ámbito específico (ej.${requestScope.usuario}).${nombre}: Busca el dato en los ámbitos en orden (pageScope,requestScope,sessionScope,applicationScope). Asegúrate de que el nombre sea único.
Caso de Uso de EL
<body>
<%
request.setAttribute("key1", "valor1");
session.setAttribute("key2", "valor2");
application.setAttribute("key3", "valor3");
%>
<%-- Acceso a través de objetos de ámbito --%>
<h1><%= request.getAttribute("key1") %></h1>
<h1><%= session.getAttribute("key2") %></h1>
<h1><%= application.getAttribute("key3") %></h1>
<hr/>
<%-- Acceso a través de EL --%>
<h1>${requestScope.key1}</h1>
<h1>${sessionScope.key2}</h1>
<h1>${applicationScope.key3}</h1>
<hr/>
<h1>${key1}</h1>
<h1>${key2}</h1>
<h1>${key3}</h1>
</body>
Diferencia entre EL y Scripts JSP
<%= request.getAttribute("nombre") %>: Devuelvenullsi no se encuentra.${requestScope.nombre}: Devuelve una cadena vacía ("") si no se encuentra.
Aplicación (Tipos de Referencia)
Al acceder a propiedades de objetos con EL, solo se pueden invocar métodos get que sigan las convenciones de nomenclatura.
<%@ page import="com.dz.entity.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>EL Accediendo a Objetos</title>
</head>
<body>
<%
User user = new User("Mundo", "123");
request.setAttribute("usuario", user);
%>
${usuario}<br> <!-- Imprime la representación del objeto -->
${usuario.username}<br> <!-- Llama a usuario.getUsername() -->
${usuario.password}<br> <!-- Llama a usuario.getPassword() -->
</body>
</html>
Aplicación (Arrays y Colecciones)
EL puede acceder a elementos de arrays, Listas y Mapas. Los Set no se pueden acceder directamente por índice.
<%
int[] array = {1, 2, 3, 4, 5};
request.setAttribute("miArray", array);
List<String> lista = new ArrayList<>();
lista.add("A");
lista.add("B");
lista.add("C");
request.setAttribute("miLista", lista);
Map<String, String> mapa = new HashMap<>();
mapa.put("ES", "España");
mapa.put("US", "Estados Unidos");
mapa.put("UK", "Reino Unido");
request.setAttribute("miMapa", mapa);
%>
<%-- Acceso EL --%>
${miArray[0]} <br>
${miArray[1]} <br>
<hr>
${miLista[0]} <br>
${miLista.get(1)} <br> <!-- Método get también es posible -->
<hr>
${miMapa["ES"]} <br>
${miMapa.US} <br>
Operadores EL
| Operador | Descripción |
|---|---|
. |
Acceso a propiedad de bean o entrada de mapa. |
[] |
Acceso a elemento de array o lista. |
+ |
Suma. |
- |
Resta. |
* |
Multiplicación. |
/ o div |
División. |
% o mod |
Módulo. |
== o eq |
Igualdad. |
!= o ne |
Desigualdad. |
< o lt |
Menor que. |
> o gt |
Mayor que. |
<= o le |
Menor o igual que. |
>= o ge |
Mayor o igual que. |
&& o and |
Y lógico. |
|| o or |
O lógico. |
! o not |
Negación lógica. |
empty |
Comprueba si un valor es nulo o vacío. |
Ejecución de Operaciones con EL
<%
request.setAttribute("num", 100);
request.setAttribute("cadenaVacia", "");
request.setAttribute("valorNulo", null);
%>
<h1>Operadores Aritméticos</h1>
<h1>${num + 2}</h1>
<h1>${num - 2}</h1>
<h1>${num * 2}</h1>
<h1>${num div 2}</h1>
<h1>${num mod 2}</h1>
<hr>
<h1>Operadores Relacionales</h1>
<h1>${num eq 101}</h1>
<h1>${num ne 101}</h1>
<h1>${num lt 101}</h1>
<h1>${num gt 101}</h1>
<h1>${num le 101}</h1>
<h1>${num ge 101}</h1>
<hr>
<h1>Operadores Lógicos</h1>
<h1>${num > 100 and num < 200}</h1>
<h1>${num > 100 or num < 200}</h1>
<h1>${not (num > 100)}</h1>
<hr>
<h1>Operador empty</h1>
<h1>${empty cadenaVacia}</h1>
<h1>${empty valorNulo}</h1>
Palabra Clave empty
empty devuelve true si el valor es null o una cadena vacía.
<%
request.setAttribute("cadenaVacia", "");
request.setAttribute("valorNulo", null);
%>
<h1>Operador empty</h1>
<h1>${empty cadenaVacia}</h1> <!-- true -->
<h1>${empty valorNulo}</h1> <lt;!-- true -->
Objetos Implícitos de EL
EL define 11 objetos implícitos:
pageScoperequestScopesessionScopeapplicationScopeparam(parámetros de solicitud, comoString)paramValues(parámetros de solicitud, comoString[])header(cabeceras HTTP, comoString)headerValues(cabeceras HTTP, comoString[])initParam(parámetros de inicialización del contexto)cookie(valores de cookies)pageContext
Obtener el Contexto de la Aplicación
<%=request.getContextPath()%>
${pageContext.request.contextPath}
Obtener Objetos de Cookie
<h1>${cookie.nombreUsuario}</h1> <!-- Obtiene el objeto cookie 'nombreUsuario' -->
<h1>${cookie.nombreUsuario.value}</h1> <!-- Obtiene el valor de la cookie 'nombreUsuario' -->
JSTL (JavaServer Pages Standard Tag Library)
Problemas Actuales
- EL es principalmente para obtener datos y realizar cálculos/condiciones simples, pero no para control de flujo complejo.
- EL no soporta iteración directa sobre colecciones para generar listados dinámicos.
¿Qué es JSTL?
JSTL es una biblioteca estándar de etiquetas para JSP que proporciona funcionalidades para lógica de control, iteración y manipulación de datos.
Propósito de JSTL
Permite realizar operaciones lógicas sobre los datos obtenidos con EL y colaborar con EL para la visualización de datos.
Uso de JSTL
- Descargar los archivos JAR:
standard.jaryjstl.jar. - Copiar estos JARs en el directorio
/WEB-INF/lib/de tu proyecto. - Importar la biblioteca de etiquetas en el JSP:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Etiquetas Principales
Etiqueta Condicional c:if
Sintaxis: <c:if test="condición">...</c:if>
<%
request.setAttribute("nombreUsuario", "admin");
%>
${nombreUsuario}
<%-- El atributo 'test' usa expresiones EL --%>
<c:if test="${nombreUsuario eq 'admin'}">
<h1>Bienvenido, ${nombreUsuario}</h1>
</c:if>
<c:if test="${nombreUsuario ne 'admin'}">
<h1>Por favor, inicie sesión.</h1>
</c:if>
Condiciones Múltiples c:choose, c:when, c:otherwise
Sintaxis:
<c:choose>
<c:when test="condición1">Resultado 1</c:when>
<c:when test="condición2">Resultado 2</c:when>
<c:otherwise>Resultado por defecto</c:otherwise>
</c:choose>
<%
request.setAttribute("edad", 25);
%>
<c:choose>
<c:when test="${edad lt 18}"><h1>Menor de edad</h1></c:when>
<c:when test="${edad ge 18 and edad lt 30}"><h1>Joven</h1></c:when>
<c:when test="${edad ge 30 and edad lt 50}"><h1>Adulto</h1></c:when>
<c:otherwise><h1>Mayor</h1></c:otherwise>
</c:choose>
Iteración c:forEach
Sintaxis:
<c:forEach
var="nombreVariable"
items="coleccion"
begin="indiceInicio"
end="indiceFin"
step="incremento"
varStatus="estadoIteracion">
<%-- Contenido del bucle --%>
</c:forEach>
<%
List<String> lista = Arrays.asList("A", "B", "C", "D", "E");
request.setAttribute("miLista", lista);
%>
<%-- varStatus proporciona información sobre la iteración actual --%>
<%-- first: Es la primera iteración? --%>
<%-- last: Es la última iteración? --%>
<%-- count: Número de la iteración actual (comienza en 1) --%>
<%-- index: Índice del elemento actual (comienza en 0) --%>
<c:forEach var="valor" items="${miLista}" begin="0" end="4" step="1" varStatus="vs">
<h1>${valor} ${vs.first} ${vs.last} ${vs.count} ${vs.index}</h1>
</c:forEach>
Etiqueta c:url
Ayuda a la reescritura de URLs para mantener la sesión cuando las cookies están deshabilitadas (añadiendo jsessionid).
<%-- Método antiguo: response.encodeRedirectURL --%>
<a href="<%=response.encodeRedirectURL(request.getContextPath()+"/ruta/pagina.jsp") %>">Enlace</a><br>
<%-- Nuevo método con c:url --%>
<c:url var="enlace" context="${pageContext.request.contextPath}" value="/ruta/pagina.jsp"/>
<a href="${enlace}">Enlace 2</a>
<%-- En acciones de formulario --%>
<form action="<c:url context='${pageContext.request.contextPath}' value='/ruta/procesar.jsp'></c:url>">
<input type="submit" value="Enviar">
</form>
Recomendación: Siempre use c:url para cualquier enlace o redirección.
Integración con JSTL y EL
Reemplazo de código de script por EL y JSTL en el proyecto EmpProject.
showAllEmp.jsp (con EL y JSTL)
<%@ page import="com.dz.emp.entity.Emp" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Consulta de Todos los Empleados</title>
</head>
<body>
<form action="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showInsertEmp.jsp'></c:url>">
<p><input type='submit' value='Nuevo'></p>
</form>
<table border='1'>
<tr>
<td>ID</td>
<td>Nombre</td>
<td>Salario</td>
<td>Edad</td>
<td colspan='2'>Acciones</td>
</tr>
<c:forEach var="emp" items="${empList}">
<tr>
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.salary}</td>
<td>${emp.age}</td>
<td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/removeEmpController?id=${emp.id}'></c:url>">Eliminar</a></td>
<td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showEmpController?id=${emp.id}'></c:url>">Modificar</a></td>
</tr>
</c:forEach>
</table>
</body>
</html>
showUpdateEmpInfo.jsp (con EL y JSTL)
<%@ page import="com.dz.emp.entity.Emp" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Modificar Información de Empleado</title>
</head>
<body>
<form action="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/updateEmpController'></c:url>" method='post'>
<p>ID:<input type='text' name='id' value=${emp.id} readonly></p>
<p>Nombre:<input type='text' name='name' value=${emp.name}></p>
<p>Salario:<input type='text' name='salary' value=${emp.salary}></p>
<p>Edad:<input type='text' name='age' value=${emp.age}></p>
<p><input type='submit' value='Actualizar'></p>
</form>
</body>
</html>
showInsertEmp.jsp (con EL y JSTL)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Alta de Empleado</title>
</head>
<body>
<form action='<c:url context="${pageContext.request.contextPath}" value="/manager/safe/insertEmpController"></c:url>' method='post'>
<p>Nombre:<input type='text' name='name'></p>
<p>Salario:<input type='text' name='salary'></p>
<p>Edad:<input type='text' name='age'></p>
<p><input type='submit' value='Enviar'></p>
</form>
</body>
</html>
Framework MVC (Modelo-Vista-Controlador)
Concepto MVC
MVC es un patrón de diseño de software que divide una aplicación en tres componentes interconectados:
- Modelo (Model): Representa los datos y la lógica de negocio.
- Vista (View): La interfaz de usuario que presenta los datos al usuario.
- Controlador (Controller): Maneja las interacciones del usuario, actualiza el modelo y selecciona la vista a mostrar.
Detalles del Patrón MVC
MVC es un patrón común en arquitecturas B/S:
- Vista: La interfaz con la que interactúa el usuario (HTML, JSP, etc.).
- Controlador: Gestiona el flujo de la aplicación, procesa solicitudes y decide qué vista mostrar.
- Modelo: Representa los datos y la lógica de negocio (usualmente compuesto por Service, DAO y Entidades).
Ventajas
- Bajo Acoplamiento: Los componentes son independientes, facilitando cambios.
- Alta Mantenibilidad: Permite reemplazar o modificar módulos fácilmente.
- Alta Reutilización: La lógica de acceso a datos puede servir a múltiples procesos de negocio.
Aplicación en Frameworks
MVC es la base de muchos frameworks Java como Struts y Spring MVC.
Paginación
Concepto
La paginación es esencial para mostrar grandes volúmenes de datos de forma manejable, dividiendo los resultados en páginas.
Estrategia de Implementación
Se recuperan solo los datos necesarios para la página actual. Por ejemplo, para mostrar 20 registros por página:
SELECT * FROM tabla LIMIT 0, 20; -- Página 1
SELECT * FROM tabla LIMIT 20, 20; -- Página 2
SELECT * FROM tabla LIMIT 40, 20; -- Página 3
Implementación del Código
- Definir el número de elementos por página.
- Calcular el número total de páginas.
- Escribir la consulta SQL para la paginación.
- Configurar la visualización de la paginación en el JSP.
Preparación de la Base de Datos
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20) NOT NULL,
salary DOUBLE NOT NULL,
age INT NOT NULL
) CHARSET=utf8;
-- Insertar datos de ejemplo
INSERT INTO emp(NAME, salary, age) VALUES('Empleado1', 1000, 18);
-- ... (insertar más registros) ...
Archivo de Configuración de Base de Datos db.properties
# Configuración de conexión
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/emp?useUnicode=true&characterEncoding=UTF-8
username=root
password=root
# Pool de conexiones
initialSize=10
maxActive=50
minIdle=5
maxWait=5000
Clase PageBean (o Page)
Esta clase contiene la información necesaria para la paginación:
pageIndex: Número de página actual.pageSize: Elementos por página.totalCounts: Total de registros.totalPages: Total de páginas.startRows: Fila de inicio para la consulta.
package com.dz.emp.entity;
public class Page {
```
private Integer pageIndex; // Número de página actual
```
private Integer pageSize; // Elementos por página
```
private Integer totalCounts; // Total de registros
```
private Integer totalPages; // Total de páginas
```
private Integer startRows; // Fila de inicio (calculada)
```
// Constructor con página y tamaño
```
public Page(Integer pageIndex, Integer pageSize) {
```
this.pageIndex = pageIndex;
```
this.pageSize = pageSize;
```
this.startRows = (pageIndex - 1) * pageSize;
```
}
```
// Constructor con solo página, tamaño fijo a 5
```
public Page(Integer pageIndex) {
```
this(pageIndex, 5);
```
}
```
// Getters y Setters...
```
// Lógica para calcular totalPages al establecer totalCounts
```
public void setTotalCounts(Integer totalCounts) {
```
this.totalCounts = totalCounts;
```
this.totalPages = (totalCounts % pageSize == 0) ? totalCounts / pageSize : (totalCounts / pageSize) + 1;
```
}
```
// ... resto de getters y setters
}
Interfaz EmpDao
package com.dz.emp.dao;
import com.dz.emp.entity.Emp;
import com.dz.emp.entity.Page;
import java.util.List;
public interface EmpDao {
```
// ... otros métodos ...
```
List<Emp> selectAll(Page page); // Para consulta paginada
```
long selectCounts(); // Para obtener el total de registros
}
#### Implementación `EmpDaoImpl`
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
// Asumiendo una clase DbUtils para obtener conexiones
public class EmpDaoImpl implements EmpDao {
```
private QueryRunner queryRunner = new QueryRunner();
```
@Override
```
public List<Emp> selectAll(Page page) {
```
try {
```
return queryRunner.query(DbUtils.getConnection(),
```
"SELECT * FROM emp LIMIT ?, ?",
```
new BeanListHandler<Emp>(Emp.class),
```
page.getStartRows(), page.getPageSize());
```
} catch (SQLException e) {
```
e.printStackTrace();
```
}
```
return null;
```
}
```
@Override
```
public long selectCounts() {
```
try {
```
return queryRunner.query(DbUtils.getConnection(),
```
"SELECT COUNT(*) FROM emp",
```
new ScalarHandler<Long>());
```
} catch (SQLException e) {
```
e.printStackTrace();
```
}
```
return 0;
```
}
```
// ... otros métodos ...
}
Interfaz EmpService
package com.dz.emp.service;
import com.dz.emp.entity.Emp;
import com.dz.emp.entity.Page;
import java.util.List;
public interface EmpService {
```
// ... otros métodos ...
```
List<Emp> showAllEmp(Page page); // Método para obtener datos paginados
}
Implementación EmpServiceImpl
import java.util.ArrayList;
// Asumiendo DbUtils para transacciones
public class EmpServiceImpl implements EmpService {
```
private EmpDao empDao = new EmpDaoImpl();
```
@Override
```
public List<Emp> showAllEmp(Page page) {
```
List<Emp> empList = new ArrayList<>();
```
try {
```
DbUtils.begin(); // Iniciar transacción
```
long count = empDao.selectCounts();
```
page.setTotalCounts((int) count); // Actualizar el total de registros y páginas en Page
```
List<Emp> data = empDao.selectAll(page);
```
if (data != null) {
```
empList = data;
```
}
```
DbUtils.commit(); // Confirmar transacción
```
} catch (Exception e) {
```
DbUtils.rollback(); // Revertir transacción
```
e.printStackTrace();
```
}
```
return empList;
```
}
```
// ... otros métodos ...
}
Controlador ShowAllEmpController
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/manager/safe/showAllEmpController")
public class ShowAllEmpController extends HttpServlet {
```
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
```
String pageIndexStr = request.getParameter("pageIndex");
```
if (pageIndexStr == null) {
```
pageIndexStr = "1"; // Página por defecto si no se especifica
```
}
```
int pageIndex = Integer.parseInt(pageIndexStr);
```
Page page = new Page(pageIndex); // Crear objeto Page
```
EmpService empService = new EmpServiceImpl();
```
List<Emp> empList = empService.showAllEmp(page);
```
if (empList != null) {
```
request.setAttribute("pageInfo", page); // Pasar información de paginación a la vista
```
request.setAttribute("empList", empList); // Pasar la lista de empleados
```
request.getRequestDispatcher("/manager/safe/showAllEmp.jsp").forward(request, response);
```
} else {
```
// Manejar el caso de error o lista vacía
```
response.getWriter().write("Error al cargar empleados.");
```
}
```
}
```
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
```
doPost(request, response); // Reenviar GET a POST
```
}
}
### `showAllEmp.jsp` (con Paginación usando EL y JSTL)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${empty empList}">
<tr>
<td colspan="6">No hay empleados para mostrar.</td>
</tr>
</c:if>
<c:forEach var="emp" items="${empList}">
<tr>
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.salary}</td>
<td>${emp.age}</td>
<td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/removeEmpController?id=${emp.id}'></c:url>">Eliminar</a></td>
<td><a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showEmpController?id=${emp.id}'></c:url>">Modificar</a></td>
</tr>
</c:forEach>
<%-- Botón "Anterior" solo si no estamos en la primera página --%>
<c:choose>
<c:when test="${pageInfo.pageIndex gt 1}">
<a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${pageInfo.pageIndex - 1}'/>">Anterior</a>
</c:when>
<c:otherwise>
<span>Anterior</span> <!-- O un enlace deshabilitado -->
</c:otherwise>
</c:choose>
<%-- Mostrar número de página actual y total --%>
<span class="current">Página ${pageInfo.pageIndex} de ${pageInfo.totalPages}</span>
<%-- Botón "Siguiente" solo si no estamos en la última página --%>
<c:choose>
<c:when test="${pageInfo.pageIndex lt pageInfo.totalPages}">
<a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${pageInfo.pageIndex + 1}'/>">Siguiente</a>
</c:when>
<c:otherwise>
<span>Siguiente</span> <!-- O un enlace deshabilitado -->
</c:otherwise>
</c:choose>
<!-- Enlace a la última página -->
<a href="<c:url context='${pageContext.request.contextPath}' value='/manager/safe/showAllEmpController?pageIndex=${pageInfo.totalPages}'/>">Última</a>
</c:if>
### Diagrama de Ejecución
Cuando el usuario solicita la página de empleados, el flujo es:
1. El navegador envía una solicitud a `/manager/safe/showAllEmpController`.
2. El `ShowAllEmpController` (un Servlet) recibe la solicitud.
3. Extrae el parámetro `pageIndex` (si existe).
4. Crea un objeto `Page` con la información de paginación.
5. Llama al `EmpService` para obtener la lista de empleados y la información de paginación.
6. El `EmpService` interactúa con `EmpDao` para obtener los datos y el total de registros.
7. El `EmpDao` ejecuta consultas SQL con `LIMIT` y `COUNT(\*)`.
8. Los datos y el objeto `Page` se guardan en el `request`.
9. La solicitud se reenvía a `/manager/safe/showAllEmp.jsp`.
10. El JSP utiliza EL y JSTL para mostrar la lista de empleados y los controles de paginación.
</body></html>