La presentación con las JSP
Introducción
Los servlets no son adecuados para gestionar de manera eficaz la visualización, como ha podido comprobar en el capítulo anterior. La plataforma Jakarta EE ofrece una solución llamada JSP (Jakarta Server Pages). Esta tecnología facilita la creación de contenido dinámico en formato HTML o XML. Se corresponde con la V (vista) de la arquitectura MVC. El servlet se encarga del procesamiento de negocio y cuando termina, delega la visualización a una JSP. En el resto del capítulo se usará contenido HTML como ejemplo.
Las JSP sencillamente son páginas de extensión HTML .jsp en las que es posible añadir diferentes tipos de contenido (no HTML), que serán procesados por el contenedor de servlets para generar un renderizado específico, relacionado con el contexto de ejecución de la consulta. Estos tipos de contenido pueden ser:
-
scripts en forma de código Java,
-
scripts en forma de EL (Jakarta Expression Language),
-
acciones estándar,
-
etiquetas estándar (JSTL - Jakarta Standard Tag Library),
-
o etiquetas personalizadas.
Este capítulo explica el principio de funcionamiento de las JSP y, posteriormente, presenta los diferentes tipos de contenido enumerados con anterioridad.
En este capítulo se analizan diferentes tecnologías.
En primer lugar, JSP, que se encuentra actualmente en su versión 3.0. Puede ver la especificación...
El proyecto
1. Crear el proyecto
El resto del capítulo se basa en un proyecto de ejemplo, denominado Proyecto_JSP.
Cree un proyecto de tipo Gradle, con las mismas características que el del primer capítulo.
Complete el árbol de directorios para que tenga este aspecto:
Agregue un archivo denominado web.xml en el directorio src/main/webapp/WEB-INF, con un contenido equivalente al del proyecto inicial (PrimerPROWeb). Simplemente, asegúrese de cambiar el nombre del proyecto dentro de la etiqueta <display-name>.
Modifique el archivo build.gradle con el siguiente contenido (consulte la sección de dependencies para hacer referencia a la API de los servlets y a la de las JSP):
plugins {
id 'java'
id 'war'
}
repositories {
jcenter()
}
dependencies {
compileOnly "jakarta.servlet:jakarta.servlet-api:5.0.0"
compileOnly group: 'jakarta.servlet.jsp', name:
'jakarta.servlet.jsp-api', version: '3.0.0'
}
Seleccione el menú contextual Gradle - Refresh Gradle Project de su proyecto para descargar las dependencias.
El proyecto está listo para manipular...
El principio de ejecución
Las JSP existen para simplificar la creación de contenido dinámico porque los servlets no están adaptados para esta tarea. Cuando una solicitud HTTP implica la ejecución de una JSP, estas son las acciones que se desencadenan:
-
Si la JSP nunca se ha utilizado antes, se transforma en una clase Java (Translation phase) antes de ser compilada. La transformación la realiza el motor Jasper 2 y la compilación la realiza, de forma predeterminada, el compilador de Java Eclipse JDT (no javac). Para obtener más información, consulte la documentación oficial en la siguiente dirección:https://tomcat.apache.org/tomcat-10.0-doc/jasper-howto.html
Esta clase debe implementar la interfaz jakarta.servlet.Servlet. En el entorno Tomcat, deriva indirectamente de la clase jakarta.servlet.http.HttpServlet. Por lo tanto, una JSP no es ni más ni menos que un servlet. La clase también debe implementar la interfaz jakarta.servlet.jsp.HttpJspPage.
Esta interfaz obliga a escribir el método _jspService(...). Este método es el equivalente de los métodos doXXX(...) de los servlets. Recibe como argumento un objeto de tipo HttpServletRequest y otro de tipo HttpServletResponse. Su función es crear una respuesta para el usuario.
A continuación, se llama al método service(...) de esta nueva clase, que llamará al método _jspService(...).
El ciclo de vida de una JSP es el mismo que el de un servlet. La única diferencia es el nombre de los métodos de inicialización y destrucción. Se llaman jspInit() y jspDestroy(). Si es necesario, se pueden redefinir en la página JSP. Para obtener más detalles, consulte el capítulo que trata sobre servlets y la sección Configurar una JSP, más...
Configurar una JSP
Normalmente, una JSP se encuentra en el directorio webapp del proyecto. Por lo tanto, es accesible a través de una URL desde el navegador de un cliente. Sin embargo, si desea ser estricto en la arquitectura MVC, una JSP no debe ser accesible directamente a través de una URL. Es necesario pasar por un servlet que delegue, llegado el momento, la generación de la respuesta a una JSP. Para ello, es posible mover la JSP al directorio WEB-INF, al que no se puede acceder a través de una URL.
El problema ahora es poder delegar la generación de la respuesta a la JSP desde un servlet. Como sucede con los servlets, el trabajo se realiza utilizando RequestDispatcher.
A continuación, se muestra un ejemplo de este mecanismo:
Cree una JSP llamada PaginaProtegida.jsp en el subdirectorio WEB-INF/jsp:
A continuación, cree un servlet denominado AccesoPaginaProtegida. El papel de este servlet es delegar la generación de la respuesta a la JSP.
El código para este servlet se puede escribir de dos maneras diferentes:
-
La primera forma consiste en utilizar el método getRequestDispatcher(...) del objeto de tipo HttpServletRequest. Este método espera una dirección URL. Como estamos a nivel del servidor, la URL puede contener una ruta a un recurso en el directorio WEB-INF. A continuación, se muestra el código para el método doGet(...):
protected void doGet(HttpServletRequest...
Las directivas
1. Presentación
Las directivas son mensajes dirigidos al contenedor para darle indicaciones sobre la etapa de transformación. Las directivas no producen contenido. La sintaxis de una directiva es la siguiente:
<%@ nombre_de_la_directiva {attr="value"}* %>
Una directiva puede tener más de un atributo.
Hay tres directrices:
-
la directiva page,
-
la directiva taglib,
-
la directiva include.
2. La directiva page
a. Presentación
Esta directiva permite definir características específicas de la página. Estas características están destinadas al contenedor para la fase de transformación. Puede haber varias directivas page en una JSP. Estas directivas se pueden colocar en cualquier lugar de la página. Hay una excepción para los atributos pageEncoding y contentType, que deben estar en una directiva de página en la parte superior de la JSP. Cada atributo debe estar presente, como máximo, solo una vez. Hay una excepción para el atributo import, para permitir que se importen varios paquetes o clases en la JSP.
Si no se respetan estas reglas, se produce un error durante la fase de transformación.
3. Atributos de la directiva
A continuación, se muestran los atributos disponibles de la directiva page:
-
language: este atributo define el lenguaje utilizado para los scripts escritos en la JSP que se deben ejecutar en el lado del servidor. Hasta ahora, el único valor posible es java. A continuación, se muestra el valor predeterminado.
-
extends: este atributo permite definir el nombre de la clase (totalmente cualificada) de la que deriva la JSP. Este atributo se debe usar con precaución. En ausencia de este atributo, el contenedor utiliza la clase predeterminada. En el entorno Tomcat, esta es la clase org.apache.jasper.runtime.HttpJspBase.
-
import: este atributo permite definir las importaciones de paquetes y clases necesarias para que los scripts escritos en Java funcionen en la JSP. Este atributo puede estar presente varias veces para mejorar la lectura. Si está presente una sola vez, las diferentes importaciones están separadas por una coma. Se importan implícitamente los paquetes java.lang.*, jakarta.servlet.* y jakarta.servlet.http.*.
-
session: este atributo espera un booleano para indicar si es posible usar la sesión HTTP en la JSP. Si es true, entonces hay disponible...
Elementos de script
1. Presentación
Los elementos de script se usan mucho en una página JSP. Hacen que el contenido sea dinámico. Hay dos tipos principales de scripts:
-
Los scripts escritos en Java, que se presentan en las siguientes secciones.
-
Los scripts escritos en EL, que se presentan más adelante en el capítulo.
Los elementos de script permiten hacer una mezcla de código, normalmente una mezcla de Java/HTML.
Los ejemplos de esta sección se encuentran en el archivo LosElementosDeScript .jsp:
2. Declaraciones
a. Presentación
Las declaraciones son elementos de script que permiten declarar variables miembro y métodos en la clase Java generada a partir de la página JSP. El código se debe escribir en la página JSP entre las siguientes etiquetas:
<%! Sus variables miembro y métodos %>
Puede haber varias zonas de declaración en la página JSP. Por lo general, solo hay una al principio de la página, para mejorar la legibilidad. Las variables miembro y los métodos declarados se pueden utilizar en los diferentes elementos de script de la página y a través de EL.
b. Ejemplo de implementación
El siguiente ejemplo muestra la declaración de una variable miembro contador y un método incrementar():
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%!
//Declaraciones de las variables miembro y los métodos
private int contador = 0;
private void incrementar()
{
this.contador++;
}
%>
<!DOCTYPE html>
<html>
<!--...-->
</html>
Durante la transformación de la JSP, este...
Objetos disponibles en una JSP
1. Presentación
Los elementos de script de tipo scriptlets y las expresiones se escriben en el método _jspService(...) durante la transformación de la página JSP en una clase Java. Como tal, estos elementos de script pueden acceder a las variables locales de este método. Hay una serie de variables potencialmente disponibles. A continuación, se muestra la lista:
-
El objeto request de tipo HttpServletRequest: este objeto tiene la misma función que en un servlet.
-
El objeto reponse de tipo HttpServletResponse: este objeto tiene la misma función que en un servlet.
-
El objeto pageContext de tipo jakarta.servlet.jsp.PageContext: este objeto permite acceder al contexto de la página. Proporciona acceso a los diversos objetos presentados en esta lista. Este objeto también proporciona métodos para manipular los atributos de los diferentes contextos representados como constantes:
-
PageContext.APPLICATION_SCOPE,
-
PageContext.REQUEST_SCOPE,
-
PageContext.SESSION_SCOPE,
-
PageContext.PAGE_SCOPE.
Estos métodos son:
-
getAttribute(String name, int scope): este método permite obtener el valor de un atributo en un contexto determinado.
-
setAttribute(String name, int scope): este método permite escribir el valor de un atributo en un contexto determinado.
-
removeAttribute(String name, int scope): este método permite eliminar el valor de un atributo en un contexto determinado.
-
findAttribute(string name): este método permite obtener el valor de un atributo, buscándolo en diferentes contextos, en el siguiente orden: PAGE_SCOPE, REQUEST_SCOPE, SESSION_SCOPE y APPLICATION_SCOPE. El método devuelve el primer valor encontrado o null. Este método se utiliza mucho en EL.
-
-
El objeto session de tipo HttpSession: este objeto tiene la misma función que en un servlet. Este objeto no está disponible si la directiva page tiene el atributo session con valor false.
-
El objeto application de tipo ServletContext: este objeto tiene la misma función que en un servlet. Como recordatorio, en un servlet, este objeto es accesible a través del método getServletContext() de la clase HttpServlet.
-
El objeto config...
Administrar los errores
1. Presentación
Debido a la tecnología utilizada, los errores pueden ocurrir en dos momentos distintos. El primer momento corresponde a la fase de transformación. Este paso puede provocar un error. El segundo momento se corresponde con la fase de ejecución. Un código poco sólido puede provocar una excepción inesperada. Un caso funcional puede causar una excepción esperada (controlada). En las secciones siguientes, se detalla cómo gestionar estos diferentes tipos de excepciones.
2. Errores en la transformación
El origen de los errores de transformación está relacionado con un problema sintáctico, por ejemplo, a nivel de la página JSP:
-
uso indebido de directivas,
-
uso indebido de elementos de script.
El resultado es el mismo, ya sea que haya un problema con la transformación o con la compilación de la clase transformada.
En siguiente ejemplo, se resalta un error relacionado con la aplicación de un valor incorrecto al atributo buffer de la directiva page. El desarrollador escribió 10 en lugar de 10kb.
<%@page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" buffer="10"%>
El ejemplo está disponible en el archivo PaginaErrorDuranteLaTransformacion.jsp.
Cuando se ejecuta la consulta, el resultado es el siguiente:
Una excepción de tipo JasperException (en el entorno Tomcat) indica un problema con la transformación. El mensaje es suficientemente explícito como para que el desarrollador realice la corrección esperada.
Normalmente, este tipo de error no debería ocurrir...
Utilizar fragmentos
1. Presentación
Una aplicación web típica está formada por varias páginas. Es habitual que cada una de estas páginas tenga una estructura idéntica, con una cabecera, pie de página y menú idénticos. En lugar de reescribir este código tantas veces como páginas existan, es mejor centralizarlo en archivos que se incluyen en las diferentes páginas. Estos archivos no son páginas web funcionales, sino que solo contienen una parte, por lo que normalmente hablamos de fragmentos. En las siguientes secciones se muestran dos métodos para incluir un fragmento.
Una alternativa a los fragmentos es usar etiquetas personalizadas. Para obtener más información, consulte la sección Etiquetas personalizadas al final de este capítulo.
2. Inclusión estática
La directiva include permite incluir un recurso externo en la JSP durante la transformación. La utilización de esta directiva se describe en la sección Directivas - La directiva include.
El código del fragmento se copia en cada una de las clases Java de las páginas JSP que utilizan esta directiva. Si se actualiza el fragmento, todas las páginas JSP se deben transformar de nuevo para incluir los nuevos cambios. Pero no tiene que hacer nada porque el servidor Tomcat se encarga de ello la próxima vez que se ejecuten estas JSP.
3. Inclusión...
Acciones estándar
1. Presentación
Las acciones estándar son etiquetas adicionales disponibles en una página JSP para facilitar su creación. Estas etiquetas son un sustituto de los scriptlets para simplificar la escritura de páginas JSP y conseguir que este trabajo sea posible para los informáticos que no dominan el lenguaje Java. Las siguientes secciones están destinadas a presentar los aspectos principales.
2. ¿Qué es un JavaBean?
Varias etiquetas que se presentan más adelante en este capítulo utilizan la noción de JavaBean. Un JavaBean es simplemente una clase Java que respeta ciertas reglas de escritura:
-
La clase debe ofrecer un constructor sin parámetros. Este constructor puede ser el constructor implícito disponible de forma predeterminada. Si se define al menos otro constructor, es obligatorio agregar explícitamente el constructor sin parámetros a la lista de constructores disponibles.
-
Las variables miembro privadas deben ser accesibles a través de descriptores de acceso y mutadores (getters y setters). El nombre de estos métodos tiene la siguiente forma. Para una variable miembro denominada variable, el getter es getVariable() y el setter es setVariable(...). Ambos métodos forman una propiedad (Property).
-
La clase no puede ser final. Es decir, se debe poder derivar.
-
La clase debe implementar la interfaz Serializable para hacer transitar el objeto a través de la red.
Las clases del paquete fr.ediciones_eni.jakartaee.modelos, como la clase Deporte, son JavaBeans:
public class Deporte implements Serializable {
private static final long serialVersionUID = 1L;
//VARIABLES MIEMBRO
private int identificador;
//...
//ACCESORES/MUTADORES
public int getIdentificandores() {
return identificador;
}
public void setIdentificador(int identificador) {
this.identificador = identificador;
}
//...
//CONSTRUCTORES
public Deporte() {
} ...
EL (lenguaje de expresión)
1. Presentación
EL es un lenguaje de expresión eficaz para sustituir en las páginas JSP el código escrito en Java. Permite manipular objetos Java y evaluar las expresiones. No permite implementar estructuras de código condicionales o repetitivas. Para esto, es necesario usarlo junto con las etiquetas JSTL. EL también se utiliza con la tecnología JSF. Para obtener más información al respecto, consulte el capítulo El framework de presentación JSF. EL se encuentra actualmente en la versión 4.0. La especificación está disponible en: https://jakarta.ee/specifications/expression-language/4.0/jakarta-expression-language-spec-4.0.pdf
2. Sintaxis
Una expresión EL se escribe de la siguiente manera:
${ expresión }
La expresión comienza con ${ y termina con }. Entre estos dos terminales o límites, se encuentra la expresión EL. Los operadores . y [] proporcionan acceso a variables miembro y métodos de los objetos manipulados.
En el siguiente ejemplo, se lee el nombre de un cliente:
${cliente.nombre}
En el siguiente ejemplo, se lee el primer mensaje de un cliente:
${cliente.mensajes[0].mensaje}
En el siguiente ejemplo, se llama al método toString() de un cliente:
${cliente.toString()}
Cada expresión que se utiliza fuera de las etiquetas JSTL provoca la visualización del resultado obtenido porque la transformación de la página JSP genera el siguiente código Java:
out.write((java.lang.String)
org.apache.jasper.runtime.PageContextImpl.
proprietaryEvaluate("${cliente.nombre}",
java.lang.String.class,
(javax.servlet.jsp.PageContext)
_jspx_page_context,
null));
El método write(...) es responsable de la visualización.
Las siguientes secciones aclaran cómo funciona esto y las posibilidades que ofrece.
EL se puede deshabilitar en una página JSP asignando el valor true al atributo isElIgnored, de la directiva...
Etiquetas JSTL
1. Presentación
Las etiquetas JSTL (Jakarta Server Pages Standard Tag Library) están destinadas a simplificar la creación de páginas JSP. Ya no es necesario ser un desarrollador Java experimentado para crear páginas JSP. Las etiquetas JSTL están en la versión 2.0 y puede accederse a la documentación en la dirección: https://jakarta.ee/specifications/tags/2.0/jakarta-tags-spec-2.0.pdf
Las etiquetas JSTL permiten llevar a cabo procesamientos recurrentes, entre los que encontramos:
-
gestión del acceso a los recursos,
-
internacionalización (i18n) y formateo,
-
gestión del acceso a la base de datos,
-
creación de contenido XML,
-
manipulación de cadenas de caracteres.
Las etiquetas JSTL están estrechamente relacionadas con EL y permiten añadir funcionalidades, como la implementación de condicionales, iteraciones, etc.
Las etiquetas JSTL se agrupan en librerías de tags (Tag Libraries). Hay cinco, como se muestra en la siguiente tabla:
Librería |
URL |
Prefijo |
Librería principal |
http://java.sun.com/jsp/jstl/core |
c |
Librería para la manipulación de XML |
http://java.sun.com/jsp/jstl/x |
x |
Librería para la internacionalización |
http://java.sun.com/jsp/jstl/fmt |
fmt |
Librería que permite el acceso a las bases de datos |
http://java.sun.com/jsp/jstl/sql |
sql |
Librería de funciones |
http://java.sun.com/jsp/jstl/functions |
fn |
En las secciones siguientes se presentan los elementos principales de las librerías principal, de internacionalización y de funciones.
2. Modificaciones en el proyecto
El JDK y Tomcat no añaden el archivo de forma nativa. Es necesario referenciarlo más adelante. Para hacer esto, simplemente modifique la sección dependencies del archivo build.gradle del proyecto Proyecto_JSP:
No olvide actualizar el proyecto, haciendo clic derecho en él y seleccionando el menú Gradle - Refresh Gradle Project.
3. Uso de una librería en una JSP
Para permitir el uso de una librería en una JSP, se debe hacer referencia a ella mediante la directiva taglib. Para obtener más información, consulte la sección La directiva taglib.
A continuación, se muestra un ejemplo para poder usar la librería principal:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Los atributos...
Etiquetas personalizadas
1. Presentación
Puede ser interesante crear etiquetas personalizadas como etiquetas JSTL. Estas etiquetas personalizadas se pueden utilizar en diferentes proyectos, mejorando así la productividad. De hecho, la librería JSTL es rica, pero las necesidades adicionales y recurrentes se hacen sentir rápidamente. El término utilizado para referirse a estas etiquetas personalizadas es tag. Por lo tanto, una etiqueta personalizada es una etiqueta que se corresponde físicamente con un archivo que se parece mucho a una página JSP.
Esto es algo equivalente al mecanismo de los fragmentos (consulte Utilizar fragmentos). Sin embargo, la tecnología implementada es diferente. La etiqueta da lugar a una clase Java durante la fase de transformación que hereda de la clase jakarta.servlet.jsp.tagext.SimpleTagSupport. En las siguientes secciones se proporciona una breve introducción al tema.
2. Crear una etiqueta personalizada
Una etiqueta personalizada es un archivo de extensión .tag en el directorio WEB-INF\tags de la aplicación. Eclipse ofrece ayuda para crear una etiqueta:
Haga clic derecho en su proyecto y después en el menú New - Other. Aparecerá la siguiente pantalla. Filtre la lista escribiendo tag en la zona Wizards:
Seleccione el tipo de archivo JSP Tag y haga clic en Next para pasar a la siguiente pantalla.
Seleccione el directorio de los tags creado anteriormente y asigne un nombre a su archivo:
Haga clic en el botón Finish. Se crea el archivo Deportes.tag con el siguiente contenido:
<%@ tag language="java" pageEncoding="UTF-8"%>
Esta directiva permite indicar que el archivo es un tag.
En este archivo, es posible utilizar todas las tecnologías presentadas en las secciones anteriores. Por ahora, la etiqueta seguirá siendo muy sencilla, únicamente con contenido estático:
<h1>Lista de los deportes</h1>
<ul>
<li>Bádminton</li>
<li>Tenis</li>
<li>Squash</li>
</ul>
3. Uso de una etiqueta personalizada
En una página JSP, es posible utilizar una etiqueta personalizada, siempre que las etiquetas disponibles en el directorio WEB-INF\tags hayan sido referenciadas...
Conclusión
Este capítulo ha presentado la riqueza de la tecnología JSP. En efecto, es posible escribir código Java en un archivo JSP, pero las acciones estándar (<jsp:XXX>), la Expression Language, las etiquetas JSTL y personalizadas invitan al desarrollador a utilizar las herramientas disponibles para aumentar la productividad y la calidad del trabajo. El siguiente capítulo expone el framework JSF para ir aún más lejos en la implementación de una solución profesional.