Sie sind auf Seite 1von 86

3

Desarrollo de Aplicaciones Web con Java EE


3
DIDÁCTICA
UNIDAD

3.  Desarrollo con Servlets y Java Server Pages


3: Desarrollo con Servlets y Java Server Pages

ÍNDICE
OBJETIVOS................................................................................................................................................................ 107
INTRODUCCIÓN....................................................................................................................................................... 108
3.1.  Introducción a HTML........................................................................................................................................... 109
3.2.  Creando Aplicaciones web con NetBeans......................................................................................................... 114
3.3. Servlet.................................................................................................................................................................. 119
3.3.1.  Conceptos básicos sobre Servlets......................................................................................................................... 120
3.3.2.  Creación de Servlets en NetBeans......................................................................................................................... 126
3.3.3.  Estructura básica de un Servlet y ciclo de vida......................................................................................................... 129
3.3.4.  Descriptor de despliegue web.xml.......................................................................................................................... 131
3.3.5.  Inicialización del servlet con ServletConfig............................................................................................................... 134
3.3.6.  Compartición de información a través de ServletContext........................................................................................... 135
3.3.7.  Persistencia en la información de sesión................................................................................................................. 139
3.3.8.  Ejemplo: mi primer Servlet.................................................................................................................................... 141
3.4.  Java Server Pages (JSPs)................................................................................................................................... 149
3.4.1.  Embebiendo sentencias Java en una JSP............................................................................................................... 149
3.4.2.  Sintaxis XML para JavaServer Pages...................................................................................................................... 150
3.4.3.  Objetos implícitos en JSPs.................................................................................................................................... 151
3.4.4.  Creando JavaServer Pages con NetBeans.............................................................................................................. 152
3.4.5.  Expression Language 2.1..................................................................................................................................... 162
3.4.6.  Tags JSP........................................................................................................................................................... 163
3.4.7.  JSTL 1.1........................................................................................................................................................... 174
3.4.8.  Configuración de web.xml para JSP....................................................................................................................... 175
3.5.  Novedades de la especificación Servlets 3.0.................................................................................................... 178
3.5.1. Anotaciones....................................................................................................................................................... 178
3.5.2.  Despliegue con web.xml y web-fragment.xml.......................................................................................................... 184
RESUMEN................................................................................................................................................................... 187

105
3: Desarrollo con Servlets y Java Server Pages

OBJETIVOS

Comprender el concepto de Servlet, su ciclo de vida, su papel en el desarrollo de
aplicaciones web, y la diferencia entre clase, objeto e instancia.


Comprender las clases e interfaces fundamentales del API Servlets 3.0, sus atributos y
sus métodos.


Comprender el papel que juega el contendor de servlets durante la ejecución de una
aplicación web.


Comprender las diferencias que existen entre los interfaces ServletConfig y
ServletContext, así como la operativa de su uso para la inicialización de parámetros de
un servlet y una aplicación web.

■ Entender qué es una JavaServer Page y su relación con la entidad Servlet.


Conocer las reglas básicas que permiten escribir JavaServer Pages como documentos
XML.


Enumerar y utilizar los cuatro mecanismos existentes para poder embeber código fuente
Java en una JavaServer Page.


Conocer los tipos de objetos implícitos en una JSP y cómo se utilizan.


Enumerar los elementos fundamentales del lenguaje de expresión.


Conocer los tipos de etiquetas JSPs, cuál es su uso más habitual y ser capaz de poder
crear una librería personalizada de etiquetas con las características más elementales.


Escribir un descriptor de aplicación web del tipo web.xml, utilizando las etiquetas más
habituales.


Crear una aplicación web sencilla que contenga diferentes elementos como servlets,
JavaServer Pages y otros recursos web como documentos HTML o ficheros de estilos
de tipo CSS.


Crear un proyecto en NetBeans para el desarrollo de una aplicación web y saber estructurar
adecuadamente los ficheros que lo componen.

107
Desarrollo de aplicaciones Web con Java EE

INTRODUCCIÓN

En la unidad 1 hemos presentado la historia de Java El alumno está listo para comenzar a desarrollar su
y cómo ha llegado a ser lo que es hoy, así como primera aplicación web sencilla y para ello esta lección
algunos conceptos básicos sobre el protocolo HTTP, introducirá las dos herramientas imprescindibles
fundamento principal de Internet y de muchas de las que permiten la creación de aplicaciones web java:
aplicaciones que vamos a construir con Java EE. Servlets y JSPs. Además daremos una introducción al
La unidad 2 nos ha enseñado a configurar nuestro lenguaje HTML, esencial para el diseño de las páginas
entorno de desarrollo con NetBeans y nos ha que completarán la interfaz gráfica de las aplicaciones
presentado algunas herramientas útiles durante la web desarrolladas.
fase de desarrollo y pruebas de un proyecto software.

108
3: Desarrollo con Servlets y Java Server Pages

3.1.  Introducción a HTML


HTML es el acrónimo de HyperText Markup Language, en castellano lenguaje de
marcado de hipertexto. Su origen va ligado al de XML como ya se comentó en la
unidad 1, pero con algunas diferencias sintácticas y de definición de etiquetas o, como
también denominaremos, tags. HTML tiene preestablecido el significado de todas
ellas.

La siguiente tabla muestra el significado de las más habituales.

Tag HTML Descripción


<!-- --> Este tag es el utilizado para embeber comentarios en el documento HTML.
<!DOCTYPE> Establece el tipo de documento HTML (versión,…).
<a> Inserción de vínculos o marcadores.
<applet> Sirve para insertar un applet en el documento HTML.
<b> Da formato en negrita al texto que encierra.
<base> Establece la URI base a la que se puede hacer referencia posteriormente.
<body> Esta tag marca el cuerpo principal del documento HTML.
<br> Marca un salto de línea.
<button> Crea un botón HTML.
<caption> Sirve para dar título a una tabla.
<dir> Inserta una enumeración.
<div> Determina un bloque de contenido que puede tener formato propio.
<font> Sirve para definir el tipo de fuente asociada a un texto.
<form> Inserta un formulario.
< h 1 > , < h 2 > , Estos tags definen encabezados para un texto de diferentes niveles.
…,<h6>
<head> Determina el encabezado principal del documento.
<hr> Dibuja una línea horizontal.
<html> Este tag delimita por completo un documento HTML.
<i> Da formato en cursiva a un texto.
Determina una entrada de contenido en un formulario (campo de texto, check-box
<input>
de verificación, lista desplegable, etc.).
<label> Establece una etiqueta vinculada a un formulario.
<li> Inserta un elemento en una lista enumerada.
<object> Inserta recursos externos por ejemplo objetos flash (.swf),
<ol> Inserta una lista ordenada.
<p> Incluye un párrafo.
<param> Define un parámetro con nombre vinculado a un objeto insertado.

109
Desarrollo de aplicaciones Web con Java EE

Tag HTML Descripción


Engloba una sección de texto que tendrá atributos comunes, como tipo de fuente,
<span>
color, etc.
Este tag sirve para incluir formatos de hojas de estilos que se están empleando en
<style>
el documento HTML.
<table> Engloba una tabla.
<tbody> Sirve para definir el cuerpo de una tabla.
<td> Inserta una celda en una fila.
<th> Inserta una celda de encabezamiento en una tabla.
<thead> Sirve para definir el encabezado de una tabla.
<title> Sirve para asignar título a un documento HTML completo.
<tr> Inserta una fila de celdas en una tabla.
<ul> Inserta una lista no numerada.

Figura 3.1.  Etiquetas HTML más habituales.

Algunas etiquetas se utilizan en combinación, por ejemplo todas las que están
asociadas a la creación de tablas o listas (ya sean numeradas o no).

Además, hay que tener en cuenta que al contrario que en XML, las tags no están
normalizadas y pueden ser de tres tipos:

■■ Etiqueta de inicio: <span>

■■ Etiqueta de fin o cierre: </span>

■■ Etiqueta de inicio y cierre: <br/>

Además, asociados a las etiquetas HTML, pueden definirse atributos como los
siguientes:

Tag HTML Descripción

id Sirve para asignar un identificador al tag asociado. El nombre asignado, se podrá usar a lo
largo del documento HTML para ser referenciado.
Asigna un nombre de clase a un tag. La clase es un concepto vinculado a las hojas de
estilos. Por ejemplo puede definirse la clase “título_principal” que tiene determinadas
propiedades de formato (tamaño de letra, tipo de fuente, color, posición relativa, etc.) y así
evitar incluir la serie de atributos en todas las tags de este tipo.
class
Con el uso de este atributo junto con las hojas de estilos se consigue desacoplar formato
y contenido en el documento: si deseamos cambiar el estilo, bastará con hacerlo en la
definición de clase de la hoja de estilos y no en todas las etiquetas que sean de esa clase
en un documento HTML muy extenso.
Este atributo está vinculado a etiquetas como <a> y sirve para definir la URI a la que se
href hace referencia en el vínculo. Por ejemplo:

<a href=”http://www.seas.es”>SEAS ESTUDIOS ABIERTOS</a>

110
3: Desarrollo con Servlets y Java Server Pages

Tag HTML Descripción


Este atributo está vinculado a ciertos elementos como enlaces, tablas, bloques de textos y
title sirve para asignar un título a dichos elementos. En combinación con un enlace <a>, el
valor definido en title será el texto que aparezca cuando pasemos el ratón sobre él.

action Este atributo se corresponde con la tag <form> y sirve para determinar qué archivo o
ejecutable será el responsable de procesar la información recogida en el formulario.
Atributo vinculado a <form>, sirve para especificar el método por el que se enviarán los
method datos del formulario a la entidad servidora que va a procesar la información. Los valores
posibles son“get” y “post”.

width Vinculado al tag <table>, sirve para especificar el ancho de la tabla. Su valor puede
darse de forma absoluta (en pixels) o relativa (en tanto por ciento).
border Vinculado al tag <table>, define el ancho del borde de una tabla expresado en píxeles.
Vinculado al tag <tr> de las filas de una tabla, establece el tipo de alineación para el
align texto de cada celda. Sus posibles valores son left, center, right, jus-
tify o char.

valign Similar al anterior, establece el tipo de alineación vertical para el texto en una celda. Sus
valores posibles son top, middle, bottom o baseline.

Figura 3.2.  Atributos habituales de las etiquetas HTML.

En las tablas anteriores se ha recogido una muestra, a modo de ejemplo de


etiquetas y atributos que define el lenguaje HTML.
Información detallada sobre los tags HTML y sus atributos correspondientes
puede consultarse en este tutorial en castellano:
http://www.htmlquick.com/es/reference.html.

A partir de estos conceptos básicos de HTML el alumno puede profundizar a base


de práctica. Existen actualmente muchas herramientas que ofrecen la posibilidad
de generar de forma gráfica el contenido de una página web, pero desde aquí
recomendamos conocer el significado de las etiquetas para poder “retocar” a mano el
código que este tipo de programas genera automáticamente.

A modo de ejemplo, incluimos el código HTML de una página web sencilla.


<!DOCTYPE html>
<html>
<head>
<title>Curso de Aplicaciones Web con Java EE</title>
<meta http-equiv=”Content-Type”
content=”text/html; charset=UTF-8”>
</head>

111
Desarrollo de aplicaciones Web con Java EE

<body>
<h1 align=”center”>
CURSO DE APLICACIONES WEB CON JAVA EE
</h1>
<br>Esperamos que estés disfrutándolo.</br>
<p>Estás en la unidad 3 aprendiendo conceptos básicos
de HTML, como por ejemplo:</p>
<center>
<table BORDER=3 CELLSPACING=3 CELLPADDING=3
WIDTH=”579” BORDERCOLOR=”#000000” >
<tr>
<th WIDTH=”50%”><font SIZE=+1>VISUALIZACIÓN</th>
<th WIDTH=”50%”><font SIZE=+1>
ETIQUETAS REQUERIDAS
</th>
</tr>
<tr>
<td><h2>Encabezado H2</h2></td>
<td><pre><font SIZE=+1>
&lt;h2>Encabezado h2&lt;/h2></pre>
</td>
</tr>
<tr>
<td><h4>Encabezado H4</h4></TD>
<td><pre><font SIZE=+1>
&lt;h4>Encabezado h4&lt;/h4></pre>
</td>
</tr>
<tr>
<td><h6>Encabezado H6</h6></td>
<td><pre><font SIZE=+1>
&lt;h6>Encabezado h6&lt;/h6></pre>
</td>
</tr>
<tr>
<td>Texto en <b>negrita</b> o <i>cursiva</i></td>
<td><pre><font SIZE=+1>
Texto en &lt;b>negrita&lt;/b> o en
&lt;i>cursiva&lt;/i></pre>
</td>
</tr>
</table></center>
</body>
</html>
Figura 3.3.  Ejemplo de página HTML sencilla.

112
3: Desarrollo con Servlets y Java Server Pages

Que puede verse desde cualquier navegador web:

Ejemplo sencillo de página HTML.

113
Desarrollo de aplicaciones Web con Java EE

3.2.  Creando Aplicaciones web con NetBeans


Antes de exponer los conceptos teóricos necesarios sobre cómo se construyen
aplicaciones web con Java EE, vamos a hacer un repaso de cómo puede crearse la
estructura básica de un proyecto de tipo “Aplicación Web” con NetBeans.

Para ello, accedemos al menú “File → New Projec → Java Web →Web
Application” y sseleccionamos un nombre para un proyecto prueba, por ejemplo
“EjemploAplicacionWeb”. Al marcar “Use Dedicated Folder for Storing Libraries” se
generará una carpeta donde se añadirán todas las librerias que use el proyecto con
rutas relativas al directorio de la aplicación.

Figura 3.4.  Menú para la creación de un proyecto de tipo Aplicación Web.

A continuación podemos seleccionar diferentes opciones:

■■ Si es una aplicación que depende de otra, en cuyo caso deberemos seleccionar


de cuál de las ya creadas lo hace.

■■ Sobre qué servidor funcionará: en nuestro caso tenemos disponibles Glassfish o


Apache Tomcat. Seleccionaremos Glassfish (la versión puede ir cambiando con
el tiempo, por defecto tomaremos siempre la más reciente).

■■ Determinar el ContextPath o la ruta de contexto, que por defecto es el nombre


de la aplicación web.

114
3: Desarrollo con Servlets y Java Server Pages

Figura 3.5.  Opciones de configuración para la aplicación web.

El context path es la ruta de la URL que se usa para direccionar adecua-


damente las peticiones hacia un recurso de la aplicación web, bien sea un
servlet que trata una petición, o una imagen del sitio web.
Típicamente, en cualquier servidor de aplicaciones, las URL que identifican
a dichos recursos vienen dadas por el siguiente esquema:
<protocolo>://<direcciónIP_del_servidor_o_
dominioDNS>:<puerto>/ <ContextPath>/<ruta_recurso>
Así, por ejemplo:

http://localhost:8080/EjemploAplicacionWeb/index.html

Finalmente, NetBeans nos permite incluir frameworks para el desarrollo de sitios web
como Spring MVC, JavaServer Faces, Struts o Hibernate. Algunos de ellos serán
tratados en profundidad más adelante en este curso.

115
Desarrollo de aplicaciones Web con Java EE

Figura 3.6.  Opciones para incluir frameworks de desarrollo en la aplicación web.

Finalmente se crea el proyecto con un esquema similar al mostrado a continuación.

Figura 3.7.  Esquema lógico de una Aplicación Web.

Este esquema representa la organización lógica de los elementos que componen la


aplicación web, si bien difiere parcialmente del esquema físico de directorios en que
está organizado. Para verlo sobre NetBeans, seleccionamos la pestaña “Files” en el
menú izquierdo, obteniendo la siguiente vista desplegada.

116
3: Desarrollo con Servlets y Java Server Pages

Figura 3.8.  Esquema de directorios de una aplicación web.

Describimos a continuación el contenido de cada directorio:

■■ nbproject: este directorio no es propio de la aplicación web, sino que es


generado por NetBeans para contener información propia del proyecto definida
en los diferentes ficheros de configuración y propiedades (project.xml y project.
properties, respectivamente). Incluye además por defecto los ficheros de Ant
apache para que puedan ser usados por el desarrollador.

■■ lib: contiene librerías específicas bajo la forma de archivos con extensión


.jar, que son utilizados para el desarrollo del proyecto y que no forman parte de
la plataforma Java EE.

■■ src: bajo esta carpeta se incluirá el código fuente java de la aplicación


web. En nuestro caso contiene dos subcarpetas: config para incluir ficheros de
configuración de la aplicación web, y java para incluir el código fuente.

■■ web: esta carpeta contiene los recursos web que requiere la aplicación.
En esta carpeta por defecto se crea con una página de índice (el formato de
la misma dependerá de los posibles frameworks y librerias seleccionadas) y
un directorio WEB-INF que contendrá los documentos de configuración como
puede ser un XML descriptor de despliegue llamado web.xml. En él podrán
definirse diferentes parámetros de la aplicación y su contenido se verá en detalle
más adelante.

117
Desarrollo de aplicaciones Web con Java EE

Lo habitual, especialmente cuando la aplicación web es grande, es que esta


carpeta contenga a su vez otras carpetas para estructurar mejor el contenido
como por ejemplo:

□□ resources para recursos, a su vez estructurados en carpetas como img para


imágenes, hojas de estilos en carpeta ccs, objetos flash en carpets swf, etc.

□□ jsp para agrupar las JSPs del proyecto.

□□ jsf para agrupar los JSFs del proyecto.

□□ html para agrupar páginas estáticas de tipo HTML, DHTML, XHTML.

□□ xml para incluir documentos XML.

□□ Etc.

■■ build: esta carpeta contiene el resultado de la compilación del proyecto,


incluyendo por un lado los ejecutables .class y por otro el paquete desplegable
de extensión .war, estructurado de acuerdo a la especificación de Java EE.

Con estos conocimientos básicos sobre como ayuda NetBeans a comenzar con el
desarrollo de aplicaciones web, podremos ir a conocer en detalle qué es un Servlet,
de qué se compone, cómo y para qué se usa.

118
3: Desarrollo con Servlets y Java Server Pages

3.3.  Servlet
Un servlet puede definirse como un componente web basado en Java que es
gestionado por un contenedor y posee la capacidad de generar contenido HTML de
forma dinámica. Además de esto, los servlets son responsables de:

■■ La recogida de datos enviados desde el lado cliente normalmente a través de


un formulario.

■■ La lectura de datos contenidos en las cabeceras de las peticiones enviadas por


la parte cliente.

■■ El tratamiento de la información recogida y la generación de un resultado del


proceso.

■■ El envío del resultado de la lógica de negocio de vuelta al cliente.

Aunque en este curso cuando hablemos de Servlets nos vamos a estar


refiriendo únicamente a Servlets del protocolo HTTP, es interesante hacer
constar que existen Servlets para tratar peticiones de otros protocolos.
Por ejemplo, existen SipServlets que gestionan peticiones y respuestas del
protocolo SIP (Session Initiation Protocol). En este protocolo se basan por
ejemplo algunos servicios de telefonía IP como Skype.

La siguiente figura muestra un esquema sencillo de interacción entre todos los actores
del escenario de comunicación con el protocolo HTTP.

Figura 3.9.  Esquema de interacción entre cliente y servidor en aplicaciones web.

119
Desarrollo de aplicaciones Web con Java EE

Describimos a continuación el flujo de interacción representado en la figura:

1. El usuario interacciona con la aplicación web cliente en su navegador. Ciertas


acciones como consultas, o accesos a enlaces se traducirán en una petición
HTTPRequest que llegará a la aplicación web desplegada en el servidor. Esta
petición llega nuestra clase Servlet, de tipo HTTP por el protocolo utilizado y con
los datos encapsulados en el objeto HTTPServletRequest.

2. El servlet procesa la petición, y en función de los datos recogidos, redirecciona la


información necesaria a la lógica de negocio encargada de “calcular” el resultado
adecuado. Dicha lógica de negocio es en realidad un conjunto de JSPs, clases
java, EJBs, etc.

3. Puede existir un componente que se encargue de almacenar datos en una base


de datos externa al servidor.

4. Parte de la lógica de proceso de la petición puede implicar accesos a


aplicaciones externas: por ejemplo en un proceso de reserva de hotel a través
de un intermediario, se debe consultar directamente al proveedor de reservas si
existe disponibilidad.

5. Siguiendo con el ejemplo, si la reserva se ha realizado correctamente, la


aplicación puede requerir la conexión con un servidor de correo electrónico que
se encargue de enviar el mensaje de confirmación al usuario.

6. Finalmente, puede quedar grabado un registro de la transacción en la base de


datos.

7. El resultado de la transacción completa será notificado al servlet para que lo


traduzca adecuadamente a la interfaz gráfica de la aplicación web.

8. Finalmente, el servlet construye la respuesta HTTPResponse con los datos


adecuados, y la envía de vuelta al usuario.

Esto es solo un ejemplo sencillo con un único servlet que gestiona una transacción
independiente de las anteriores. En la vida real no es tan sencillo, por ello es necesario
conocer en detalle cuáles son las funcionalidades que ofrecen los Servlets y en
concreto los Servlets para gestionar el modelo de petición-respuesta del protocolo de
Internet HTTP.

3.3.1.  Conceptos básicos sobre Servlets


Una vez hemos introducido qué son y para qué sirven los servlets, lo siguiente es ver
cómo están definidos por la especificación y qué funcionalidades ofrecen.

La JSR-315 define la versión 3.0 de Servlets incluida en la plataforma Java EE 6. El


documento fue publicado en diciembre de 2009, y tiene una extensión de 230 páginas.
Aquí veremos lo fundamental, pero para aquéllos interesados en profundizar, pueden
ir directamente a la especificación en este enlace: http://jcp.org/en/jsr/detail?id=315.

120
3: Desarrollo con Servlets y Java Server Pages

Otra referencia importante para tener a mano es el javadoc del API de Servlets. Para
ello, basta con realizar la siguiente búsqueda en internet: “javax.servlet Java EE 6”, y
nos llevará a este enlace http://docs.oracle.com/javaee/6/api/javax/servlet/package-
summary.html .

Repasamos a continuación las características principales de las clases más relevantes


de la librería.

3.3.1.1.  Clase HttpServlet


Esta clase implementa el interfaz definido por javax.servlet.Servlet y hereda
métodos de javax.servlet.GenericServlet relacionados con su ciclo de vida. A
continuación se detallan los métodos más relevantes.

■■ protected void doDelete(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar el método DELETE del protocolo HTTP.

■■ protected void doGet(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar el método GET del protocolo HTTP.

■■ protected void doOptions(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar el método OPTIONS del protocolo HTTP.

■■ protected void doPost(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar el método POST del protocolo HTTP.

■■ protected void doPut(HttpServletRequest req,


HttpServletResponse resp:

Sirve para gestionar el método PUT del protocolo HTTP.

■■ protected void doTrace(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar el método TRACE del protocolo HTTP.

■■ protected void service(HttpServletRequest req,


HttpServletResponse resp):

Sirve para gestionar la recepción inicial de la petición HTTP, hacer un análisis


previo e invocar al método doXXX apropiado en función del tipo de método.

121
Desarrollo de aplicaciones Web con Java EE

■■ String getInitParameter (String name):

Sirve para obtener el valor del atributo de inicialización pasado como parámetro.

■■ ServletContext getServletContext():

Devuelve el objeto ServletContext asociado al servlet. Este objeto sirve para


identificar de forma unívoca al servlet dentro de la aplicación web desplegada
en el servidor.

■■ void init():

Este método es el primero que el contenedor de servlets invoca al crear una


instancia del objeto HttpServlet. Contendrá típicamente acciones como carga
de ficheros de propiedades, establecimientos de conexiones con componentes
externos como bases de datos, etc.

■■ void destroy():

Este método es el último que invoca el contenedor de servlets antes de destruir


la instancia del objeto HttpServlet. De forma análoga al método init(), servirá para
liberar recursos como por ejemplo pool de conexiones a bases de datos.

3.3.1.2.  Clase HttpServletRequest


Recomendamos revisar el javadoc javax.servlet.http.HttpServletRequest.
A continuación detallamos los métodos más utilizados.

■■ Object getAttribute(String name):

Devuelve el atributo asociado con el nombre pasado como argumento.

■■ java.util.Enumeration getAttributeNames():

Devuelve la enumeración que contiene los nombres de los atributos incluidos en


la petición.

■■ String getParameter(String name):

Devuelve el parámetro asociado con el nombre pasado como argumento.

■■ java.util.Map getParameterMap():

Devuelve un mapa que contiene los nombres de los atributos incluidos en la


petición.

■■ String[] getParameterValues(String name):

Devuelve un array de objetos tipo String que incluyen todos los valores asociados
con un determinado parámetro.

122
3: Desarrollo con Servlets y Java Server Pages

■■ String getContextPath():

Este método devuelve la parte de la URL que se refiere al contexto de la petición.


Es útil porque en un mismo servidor de aplicaciones pueden desplegarse varias
aplicaciones Java EE, cada una bajo su propio contexto. De esta forma la URL
tiene la forma:

Protocolo://servidor:puerto/contexto/ruta_al_fichero/nombre_
del_fichero

■■ Cookie[] getCookies():

Devuelve las cookies asociadas a la petición.

■■ String getHeader(String name):

Devuelve el contenido asociado a una cabecera HTTP específica. Algunas


cabeceras son:

□□java.util.Enumeration getHeaderNames():

Devuelve una enumeración conteniendo todas las cabeceras HTTP de la


petición.

□□java.util.Enumeration getHeader(String name):

Devuelve todos los valores asociados a la cabecera HTTP pasada como


argumento.

■■ String getMethod():

Devuelve el nombre del método empleado en la petición (GET, POST, PUT,


DELETE, etc.).

■■ HttpSession getSession():

Devuelve el objeto sesión asociado a esta petición. En caso de no existir sesión,


se devuelve una nueva.

■■ HttpSession getSession (boolean create):

Equivale al método anterior, pero solo se crea la sesión si se especifica el valor


true.

3.3.1.3.  Clase HttpServletResponse


Recomendamos revisar el javadoc javax.servlet.http.HttpResponse. A
continuación detallamos los métodos más utilizados de este objeto.

■■ java.io.PrintWriter getWriter() throws java.io.IOException:

Este método devuelve un objeto de tipo PrintWriter que es enviado al cliente.


Este objeto normalmente se usa para codificar el resultado HTML en él que el
cliente va a visualizar en su navegador.

123
Desarrollo de aplicaciones Web con Java EE

■■ void setContentType(String type):

Sirve para establecer el tipo de respuesta enviada al cliente, si es texto plano,


documento pdf, una imagen, etc.

■■ void addCookie(Cookie cookie):

Este método sirve para añadir una cookie a la respuesta enviada al cliente.

■■ void addHeader(String name, String value):

Este método es usado en el proceso de construcción de la respuesta HTTP, y en


concreto para añadir nuevas cabeceras con nombre y valor asociados.

■■ boolean containsHeader(String name):

Este método verifica si la respuesta incluye la cabecera cuyo nombre se pasa


como parámetro.

■■ String encodeRedirectURL(String url):


Prepara una URL para ser usada por el método sendRedirect.

■■ String getHeader(String name):


Devuelve el valor de la cabecera cuyo nombre se pasa como parámetro.

■■ java.util.Collection getHeaderNames():
Devuelve los nombres de las cabeceras HTTP incluidas en la respuesta.

■■ java.util.Collection getHeaders(String name):


Devuelve los valores asociados a la cabecera pasada como parámetro.

■■ void sendError (int se):

Este método envía al servidor una respuesta con el código de error HTTP
especificado.

■■ void sendRedirect(String location):


Este método redirecciona al cliente a la URL especificada como parámetro.

■■ ServletOutputStream getOutputStream():

Este método devuelve un objeto tipo ServletOutputStream que suele servir para
establecer respuestas binarias.

3.3.1.4.  Interfaz HttpSession


Este interfaz proporciona una forma de identificar al usuario a lo largo de varias
solicitudes de visita a un sitio web, y además de almacenar información relevante
sobre el propio usuario o el uso que está haciendo del sitio web. El contenedor de
servlets del servidor utiliza este interfaz para crear un mecanismo de comunicación
denominado sesión entre cliente y servidor HTTP.

124
3: Desarrollo con Servlets y Java Server Pages

La sesión persiste durante un determinado período de tiempo o mientras el usuario


esté activo en la visita del sitio web. Lo normal es que exista una relación uno a uno
entre usuario y sitio web.

Recomendamos revisar el javadoc javax.servlet.http.HttpSession para


explorar el detalle de las funcionalidades que ofrece este interfaz, si bien se recogen
algunos de los métodos más relevantes a continuación.

■■ Object getAttribute (String name):

Este método devuelve un objeto asociado al nombre de atributo pasado como


parámetro.

■■ String getId():

Este método devuelve el identificador de la sesión. El contenedor web será


responsable de gestionar las sesiones activas asociadas a una determinada
aplicación web, y asignarles un identificador único para su gestión.

■■ ServletContext getServletContext():

Devuelve el objeto ServletContext al que está vinculado la sesión.

■■ void setAttribute(String name, Object value):

Este método sirve para añadir un objeto nuevo a la sesión identificado por el
nombre de atributo.

■■ void setMaxInactiveInterval(int interval):

Este método sirve para determinar el tiempo máximo en segundos que el cliente
HTTP puede estar inactivo, sin interaccionar con el servidor HTTP, antes de que
el contendor invalide la sesión.

3.3.1.5.  Clase Cookie


Esta clase se encuentra en el paquete javax.servlet.http y representa una
cookie enviada por un servlet de la aplicación web desplegada en el servidor al
navegador web.

Como ya se vió en una unidad anterior, las cookies toman un valor numérico que
sirve para identificar de forma unívoca a un cliente, por lo que este concepto va ligado
normalmente al de gestión de sesiones.

Típicamente una cookie tiene asociada la siguiente información:

■■ Un valor numérico único.

■■ Otros atributos opcionales como comentarios, ruta, dominio, duración máxima,


versión.

125
Desarrollo de aplicaciones Web con Java EE

Los métodos típicos asociados al objeto cookie serán getX() y setX() viculados a cada
uno de los valores anteriores:
■■ String getValue() y void setValue(String newValue).
■■ String getDomain() y void setDomain(String domain).
■■ String getPath() y void setPath(String uri).

■■ etc…

Un ejemplo sobre como manipular cookies se recoge a continuación:

Cookie cookie = new Cookie(“user”,

request.getParameter(“usuario”));

cookie.setDomain(“www.seas.es”);

cookie.setComment(“Nombre de usuario”);

cookie.setMaxAge(60*60*12);

response.addCookie(cookie);

Figura 3.10.  Ejemplo de manipulación de objetos tipo Cookie.

3.3.2.  Creación de Servlets en NetBeans


NetBeans, como es habitual, nos facilita la creación de Servlets. Posicionando el
ratón sobre el paquete o proyecto donde vamos a crear el servlet seleccionamos
“New → Servlet” y veremos el siguiente cuadro de diálogo donde darle nombre y
ubicarlo en el paquete adecuado.

Figura 3.11.  Creación de nuevo servlet con NetBeans.

126
3: Desarrollo con Servlets y Java Server Pages

A continuación, usando “Next >”, podemos configurar otros aspectos del despliegue
del servlet, como su nombre y lo que denomina NetBeans como “URL Pattern”, que
no es más que la ruta relativa al servlet desde el navegador. De esta forma acceder a
él es posible con la URL:

http://[IP-host]:[puerto]/[nombre_de_la_app]/[URL_pattern]

Figura 3.12.  Configuración de aspectos de despliegue del servlet.

Se recomienda utilizar rutas relativas siempre que sea posible en nuestra


aplicación web. De esta forma, la aplicación podrá ser desplegable en cual-
quier servidor sea cual sea la dirección IP o el puerto en el que se escuchen
las peticiones HTTP.
El uso del URL Pattern nos lo garantiza, pero hay que tenerlo en cuenta
también cuando se definen en código rutas a otros recursos como imáge-
nes o clases.

NetBeans dará como resultado un nuevo fichero java con la estructura básica de un
servlet, como se muestra a continuación.

127
Desarrollo de aplicaciones Web con Java EE

package com.seas.ud3.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MiPrimerServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, Http-
ServletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet MiPrimerServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Servlet MiPrimerServlet at “ +
request.getContextPath() + “</h1>”);
out.println(“</body>”);
out.println(“</html>”);
} finally { out.close(); }
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
public String getServletInfo() {
return “Short description”;
}

}
Figura 3.13.  Estructura básica de un Serlvet creado por NetBeans.

128
3: Desarrollo con Servlets y Java Server Pages

Además, la generación del primer servlet en un proyecto de NetBeans trae como


consecuencia la creación de un nuevo fichero llamado web.xml ubicado bajo el
directorio web/WEB-INF del proyecto. Se trata de un fichero XML cuyo aspecto es
similar al mostrado a continuación.
<?xml version=”1.0” encoding=”UTF-8”?>

<web-app version=”3.0” xmlns=”http://java.sun.com/xml/ns/ja-


vaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.
sun.com/xml/ns/javaee/web-app_3_0.xsd”>
<servlet>
<servlet-name>MiPrimerServlet</servlet-name>
<servlet-class>com.seas.ud3.servlets.MiPrimerServlet</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>MiPrimerServlet</servlet-name>
<url-pattern>/MiPrimerServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>

</web-app>

Figura 3.14.  Descriptor web.xml creado por defecto por NetBeans.

Antes de explicar qué tipo de información contiene vamos a profundizar en la estructura


y ciclo de vida de los servlets.

3.3.3.  Estructura básica de un Servlet y ciclo de vida


La estructura básica se deriva del objeto GenericServlet, que define los siguientes
métodos que podemos sobrescribir al crear nuestros propios servlets.

■■ public void init() throws ServletException.

■■ public void init(ServletConfig config) throws ServletException.

■■ public void destroy().

■■ public String getInitParameter(String name).

■■ public Enumeration<String> getInitParameterNames().

■■ public ServletConfig getServletConfig().

129
Desarrollo de aplicaciones Web con Java EE

■■ public ServletContext getServletContext().

■■ public String getServletInfo().

■■ public void log(String msg).

■■ public void log(String message, Throwable t).

■■ public abstract void service(ServletRequest, req, ServletResponse


resp).

■■ public String getServletName().

Las instrucciones que típicamente van en cada uno de ellos están ligadas a su ciclo de
vida en el contenedor web, que se muestra gráficamente en la siguiente figura.

Figura 3.15.  Ciclo de vida de un Servlet.

Este diagrama podemos interpretarlo de la siguiente manera:

1. El servidor de aplicaciones envía una petición HTTP, que llega al contenedor


web. El contendor identifica que debe ser atendida por el Servlet A y éste no
existe.

2. El contendor carga la clase asociada al Servlet A y crea una instancia del objeto.

3. El contenedor invoca el método init() del Servlet e inicializa los parámetros


que correspondan.

4. El objeto está creado: éste será el responsable de gestionar todas las peticiones
HTTP que lleguen a dicho servlet.

5. Se invoca al método service(), pasando como parámetro el objeto


HTTPRequest y otro HTTPResponse.

6. El método service() analiza las cabeceras de la petición HTTP y en función


del tipo de método (GET, POST, PUT, DELETE…) invoca el método doXXX()
correspondiente.

130
3: Desarrollo con Servlets y Java Server Pages

7. Los pasos 6-7 serán ejecutados tantas veces como peticiones HTTP
correspondientes a la misma sesión se produzcan.

8. Una vez la petición ha sido procesada y enviada la HTTPResponse adecuada, el


servlet ha concluido su función.

THREADING en el manejo de Servlets.


Hemos visto que el contendor crea una instancia nueva del servlet cuando
llega una petición HTTP. Así, para un servlet A, existirán múltiples threads
corriendo simultáneamente mientras una nueva petición se está ejecutando.
Eso implica que el desarrollador deberá ser muy cuidadoso con el manejo
que hace de recursos compartidos como por ejemplo escritura sobre fiche-
ros comunes o accesos a bases de datos.
Para evitar problemas, lo que puede hacerse es implementar el interfaz
SingleThreadModel en nuestros servlets: esto garantizará que nunca
habrá más de una petición HTTP siendo gestionada por una única instancia
de un servlet. Como inconveniente, esto puede implicar un aumento de la
latencia en la gestión de las peticiones HTTP. Con lo que, una vez más en
programación, debe llegarse a una solución de compromiso.

Además, en la especificación Servlet API 3.0 se incorpora la posibilidad de poder


implementar interfaces tipo listener para diferentes eventos como por ejemplo:

■■ ServletContextListener para la inicialización y destrucción del contexto


del servlet.

■■ ServletContextAttributeListener y ServletContextAttribute
Event cuando hay alguna modificación sobre los atributos del ServletContext.

■■ HttpSessionListener, HttpSessionActivationListener y
HttpSessionEvent cuando se crea, invalida, activa, pausa o expira la sesión
vinculada a un servlet.

■■ HttpSessionBindingEvent cuando se produce algún cambio en los


atributos definidos para una sesión.

■■ ServletRequestEvent, cuando una petición del servlet comienza a ser


procesada por algún componente web.

■■ ServletRequestAttributeListener y ServletRequestAttribute
Event cuando algún atributo de la petición del servlet es modificado.

3.3.4.  Descriptor de despliegue web.xml


Hemos visto que al añadir nuestro primer servlet al proyecto en NetBeans, se añadía
también un fichero llamado web.xml bajo el directorio WEB-INF. A este documento se
le llama también descriptor de despliegue de la aplicación, y permite definir opciones
de configuración para nuestra aplicación web, así como definir la relación entre las
URL de la aplicación y las clases java correspondientes.

131
Desarrollo de aplicaciones Web con Java EE

Así, sabemos que desde un navegador, podemos acceder a nuestro servlet a través
de la URL: http://[host]:[port]/[WebApp][URLPattern], pero, ¿cómo
podemos establecer también esa correspondencia para en nuestro caso tener la URL:
http://localhost:8080/EjemploApplicacionWeb/MiPrimerServlet?.

La respuesta está en las definiciones hechas en este fichero.

Si nos fijamos en el fichero web.xml generado automáticamente, tenemos las


siguientes dos etiquetas relevantes:

■■ <servlet> es utilizada para asignar nombre a cada servlet contenido en la


aplicación web e identificarlo como <servlet-name> y vincularlo a la clase
que lo implementa especificada como <servlet-class>.

■■ <servlet-mapping> sirve para asignar una URL concreta a cada servlet


identificado por su nombre. Con <url-pattern> se especifica la ruta al servlet,
de forma que la URL completa para invocarlo desde cualquier navegador será la
definida antes: http://[host]:[port]/[WebApp][URLPattern].

El esquema de tags que debe cumplir un descriptor de despliegue de aplicaciones


web Servlet API 3.0, es el determinado por el siguiente fichero: http://java.
sun.com/xml/ns/javaee/web-app_3_0.xsd. A partir de este esquema es
posible que algunos servidores de aplicaciones sean capaces de “comprender” tags
adicionales. A continuación detallamos algunos de los tags más frecuentemente
utilizados.

■■ <display-name> sirve para asignar un nombre a la aplicación, que será con el


que se pueda diferenciar del resto de aplicaciones en el servidor.

■■ <context-param> sirve para incluir parámetros de inicialización del contexto


del servlet. Los parámetros contenidos serán los que se utilicen en la inicialización
del servlet a través de los interfaces ServletConfig y ServletContext.

■■ <session-config> define los parámetros para esta aplicación web, incluyendo


típicamente <session-timeout> para definir el período de expiración de la sesión.

■■ <welcome-file-list> define una lista ordenada de archivos que deben


servirse al cliente como página de bienvenida a la aplicación. El orden incluido
especifica una preferencia (si no existe uno, se intenta con el siguiente).

■■ <error-page> sirve para mapear códigos de error HTTP con la ruta a los
recursos web que los muestran al usuario.

■■ <jsp-config> web.xml es el descriptor de despliegue de toda la aplicación


web, y esto incluye a las JSPs que formen parte del archivo .war desplegable.
Con esta tag puede definirse aspectos de configuración para los ficheros JSPs.

■■ <login-config>:en ocasiones, los servlets gestionan procesos de autenticación


y registro. Con este tag se puede configurar qué método de autenticación debe
usarse en cada caso.

■■ <mime-mapping> sirve para establecer la relación entre tipos de extensiones


de ficheros y sus correspondiente tipos MIME.

132
3: Desarrollo con Servlets y Java Server Pages

A continuación se incluye un ejemplo más completo de descriptor web.xml incluyendo


alguno de los tags anteriores.
<?xml version=”1.0” encoding=”UTF-8”?>

<web-app version=”3.0” xmlns=”http://java.sun.com/xml/ns/ja-


vaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.
sun.com/xml/ns/javaee/web-app_3_0.xsd”>
<display-name>Un ejemplo de aplicación web</display-name>
<context-param>
<param-name>WebMaster</param-name>
<param-value>webmaster@seas.es</param-value>
</context-param>
<servlet>
<servlet-name>EjemploServlet</servlet-name>
<servlet-class>com.seas.ud3.servlets.EjemploServlet</servlet-
class>
<init-param>
<param-name>Proveedor</param-name>
<param-value>SEAS Estudios Abiertos</param-value>
</init-param>
<init-param>
<param-name>Contacto</param-name>
<param-value>info@seas.es</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>MiPrimerServlet</servlet-name>
<servlet-class>com.seas.ud3.servlets.MiPrimerServlet</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>EjemploServlet</servlet-name>
<url-pattern>/EjemploServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MiPrimerServlet</servlet-name>
<url-pattern>/MiPrimerServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<mime-mapping>
<extension>pdf</extension>

133
Desarrollo de aplicaciones Web con Java EE

<mime-type>application/pdf</mime-type>
</mime-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>

</web-app>
Figura 3.16.  Ejemplo de fichero web.xml.

3.3.5.  Inicialización del servlet con ServletConfig


Hemos visto al repasar el ciclo de vida de un Servlet, que los métodos init() y
destroy() solo serán llamados una sola vez a lo largo de toda la vida del servlet
en el contenedor, mientras que el método service() será invocado cada vez que
llegue una petición HTTP con destino al servlet en la sesión en curso.

Por lo tanto, si lo que se pretende es establecer ciertos parámetros de referencia que


permanezcan invariantes durante toda la vida del servlet y sean comunes a todos los
usuarios que accedan al servlet, con independencia de la instancia del servlet que
estén utilizando, deberá hacerse desde el método init() y más concretamente a
través del interfaz ServletConfig.

Son parámetros típicos declarados en web.xml a través de la etiqueta <init-


param> anidada en <servlet>, rutas a bases de datos con las que únicamente
interacciona el servlet, datos fijos como mails a incluir en la información de la web,
referencias a componentes EJBs utilizados por el servlet, etc. Así, por ejemplo
podemos tener definido en web.xml los siguientes parámetros:
<servlet>
<servlet-name>EjemploServlet</servlet-name>
<servlet-class>com.seas.ud3.servlets.EjemploServlet</servlet-
class>
<init-param>
<param-name>Proveedor</param-name>
<param-value>SEAS Estudios Abiertos</param-value>
</init-param>
<init-param>
<param-name>Contacto</param-name>
<param-value>info@seas.es</param-value>
</init-param>
</servlet>

134
3: Desarrollo con Servlets y Java Server Pages

Parámetros de configuración del servlet en web.xml.

Para acceder a ellos desde el servlet EjemploServlet.java, tendremos el siguiente


código para el método init():

/*Se definen variables estáticas y privadas al ámbito del servlet para almacenar los paráme-
tros de inicialización */
static private String param1;
static private String param2;
// . . .

public void init(ServletConfig config) throws ServletException{


super.init(config);
// Se cargan los parametros definidos en web.xml
EjemploServlet.param1 = getInitParameter(“Proveedor”);
EjemploServlet.param2 = getInitParameter(“Contacto”);
// . . .

Figura 3.17.  Configuración de parámetros de un servlet a través de ServletConfig.

3.3.6.  Compartición de información a través de ServletContext


Hemos visto que cuando desplegamos una aplicación web en nuestro servidor de
aplicaciones, el contenedor se encarga de crear un objeto del tipo ServletContext.
Este objeto es único para la aplicación web y servirá como método de comunicación
entre la aplicación y el contenedor. Además puede servir también:

■■ Para obtener la información de configuración del fichero de despliegue web.


xml. En concreto, dicha información será la que se encuentre definida bajo la
etiqueta <context-param>.

■■ Para servir de canal de comunicación entre los recursos tipo servlets o JSPs de
una misma aplicación web.

■■ Para modificar en tiempo de ejecución la información de configuración definida


en el fichero web.xml.

La siguiente figura muestra cómo es la relación en-


tre aplicación web, servlets y objeto ServletContext.

135
Desarrollo de aplicaciones Web con Java EE

Figura 3.18.  Relación entre aplicaciones web y objeto ServletContext.

Como se muestra la figura, existirá un único objeto ServletContextA vinculado


a la aplicación web A con independencia del número de servlets y páginas JSP que
ésta contenga.

El objeto ServletContext además es único en cada máquina virtual


Java. Este aspecto es transparente al desarrollador cuando existe una úni-
ca instancia del servidor de aplicaciones, pero no el caso en que exista una
configuración en clúster del servidor.
Cuando una aplicación web está distribuida en despliegue, esto se indica en
el fichero descriptor de despliegue del servidor, y eso hará que al desplegar
dicha aplicación, se cree una instancia en cada máquina virtual.

Los métodos más relevantes de este objeto se describen a continuación. Para


obtener más información se recomienda consultar el javadoc javax.servlet.
ServletContext.

■■ Object getAttribute (String name):

Este método devuelve un objeto conteniendo el atributo asociado al nombre


pasado como parámetro.

■■ ClassLoader getClassLoader():

Este método permite obtener el ClassLoader de la clase para cargar el valor de


los atributos.

■■ ServletContext getContext(String uripath):

Este método devuelve el objeto ServletContext vinculado a la URL especificada


como parámetro.

136
3: Desarrollo con Servlets y Java Server Pages

■■ String getContextPath():

Este método devuelve el path de contexto de la aplicación web a la que pertenece


el servlet que se está manejando.

■■ String getInitParameter(String name):

Este método devuelve el valor del atributo de inicialización.

■■ JspConfigDescriptor getJspConfigDescriptor():

Como se verá más adelante, el objeto ServletContext no es exclusivo de los


servlets, sino que también existe para las páginas JSP. Este método devuelve el
valor de la etiqueta <jsp-config> incluida en el fichero de configuración web.xml.

■■ SessionCookieConfig getSessionCookieConfig():

Este método devuelve el objeto SessionCookieconfig a través del que pueden


configurarse aspectos de sesión de las cookies empleadas en la aplicación web.

■■ Boolean setInitParameter(String name, String value):

Este método es empleado para establecer parámetros de configuración del


servlet. Típicamente valores como direcciones de acceso a sistemas externos
o nombre de ficheros con extensión .properties desde los que se cargan
parámetros de configuración de la aplicación web.

Es esencial tener clara la diferencia entre la utilidad de los interfaces Ser-


vletConfig y ServletContext.
ServletConfig proporciona una forma de acceso a los atributos nombre-
valor definidos como String en web.xml, para su compartición entre TODOS
los usuarios que instancien el servlet.
ServletContext tiene un significado todavía más global y tiene sentido a
nivel de aplicación web, es decir, de fichero desplegable .war con todos sus
recursos. Además sus atributos son parejas de String nombre y Objeto
valor. Por lo tanto, su uso está destinado para compartir información común
no sólo a un servlet específico, sino a TODOS los servlets, JSPs, etc., que
formen parte de la aplicación web.

Los parámetros habituales que forman parte del ServletContext son valores
globales a toda la aplicación web como URLs a recursos externos (bases de datos,
servidores), información de autenticación en servidores externos, pool de conexiones
a bases de datos. No hay que olvidar que es posible almacenar objetos, no solo
Strings. Vamos a ver un ejemplo de inicialización del ServletContext.

ServletContext se utiliza en combinación con el interfaz ServletConfig, dado


que el contexto es un atributo más de ServletConfig. Una vez obtenido, se le
asignan los valores especificados en las etiquetas <context-param> del descriptor
de despliegue web.xml.

137
Desarrollo de aplicaciones Web con Java EE

Así, tenemos los siguientes valores de contexto definidos en web.xml:


<context-param>
<param-name>DatabaseURL</param-name>
<param-value>jdbc:mysql://localhost:3306/midb</param-value> </
context-param>
<context-param>
<param-name>UserDB</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>PasswordDB</param-name>
<param-value>admin</param-value>

</context-param>

Figura 3.19.  Parámetros de configuración de la aplicación web en web.xml.

En el método init(ServletConfig config) podremos inicializar el


ServletContext:
@Override
public void init(ServletConfig config) throws ServletException {

super.init(config);

// . . .
ServletContext context = config.getServletContext();
String url = context.getInitParameter(“DatabaseURL”);
String user = context.getInitParameter(“UserDB”);
String password = context.getInitParameter(“PasswordDB”);

}
Figura 3.20.  Inicialización de la aplicación web a través de ServletContext.

De esta forma ya hemos conseguido que los parámetros DatabaseURL, UserDB,


PasswordDB, puedan ser accedidos desde cualquier archivo de la aplicación web
(ya sea servlet, clase java, jsp, etc.) sin más que invocarlo a través de la sentencia
getServletContext().getInitParameter(“paramX”).

138
3: Desarrollo con Servlets y Java Server Pages

3.3.7.  Persistencia en la información de sesión


HTTP es un protocolo sin estado. Eso implica que el servidor de aplicaciones no
conoce nada del usuario que ha generado la petición HTTP que ha llegado al servidor.
Pero en ocasiones, las aplicaciones necesitan tener información sobre la actividad
del usuario para ofrecer contenido personalizado de acuerdo a sus gustos o usos
del sitio, realizar transacciones largas que impliquen varias peticiones HTTP como
registros o pagos, etc. El mecanismo que permite dotar al protocolo HTTP de una
persistencia en la información manejada durante las interacciones usuario y servidor
son las SESIONES.

La programación con servlets ofrece cuatro mecanismos para mantener esa


información de estado:

■■ Cookies: especialmente utilizadas para guardar persistencia de información


entre sesiones (consecutivas o alternas) del mismo usuario.

■■ Reescritura de URLS para incluir parámetros ocultos: la información es


transferida adjuntando información al final de la URL a la que es redirigida la
respuesta resultante de procesar una petición HTTP. Esa información adjuntada
hace referencia al identificador de sesión o al identificador de cookie.

■■ Campos ocultos en los formularios. Es un mecanismo equivalente al anterior


que implica el envío de información a través de formularios.

■■ Utilización del objeto HTTPSession. Esta es la forma no programática


de gestionar la persistencia de información a través de sesiones. Es lo más
recomendable y más ampliamente utilizado. A continuación incluimos un ejemplo
que detalle cómo gestionar información de sesiones en un servlet.

Incluimos a continuación el código fuente de un servlet que gestiona el número de


accesos realizado al servlet por el usuario perteneciente al proyecto de esta unidad.
package com.seas.ud3.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
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 javax.servlet.http.HttpSession;

@WebServlet(name = “SessionServlet”, urlPatterns = {“/Session-


Servlet”})
public class SessionServlet extends HttpServlet {

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
ServletContext context = config.getServletContext();
String url = context.getInitParameter(“DatabaseURL”);

139
Desarrollo de aplicaciones Web con Java EE

String user = context.getInitParameter(“UserDB”);


String password = context.getInitParameter(“PasswordDB”);
System.out.println(“DatabaseURL: “ + url + “ | UserDB: “
+ user + “ | PasswordDB: “ + password);
}

protected void processRequest(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
// Establecemos el tipo MIME de la salida
response.setContentType(“text/html;charset=UTF-8”);

// Declaración de variables
PrintWriter out = response.getWriter();
Integer contadorAccesos;
// Devuelve la sesión si existe. Si no existe, crea una nueva.
HttpSession session = request.getSession(true);
// Los accesos al objeto sesión están sincronizados para
//garantizar la contabilización de todos los accesos al
//servlet.
synchronized(session) {
contadorAccesos = (Integer)session.getAttribute(“con-
tadorAccesos”);
if (contadorAccesos == null) {
contadorAccesos = 0;
} else {
contadorAccesos = contadorAccesos + 1;
}
session.setAttribute(“contadorAccesos”, contadorAccesos);
}

// Se genera la página HTML de respuesta


try {
out.println(“<!DOCTYPE html>”);
out.println(“<html>”);
out.println(“<head><title>
Servlet de Gestión de Sesiones
</title></head><body>”);
out.println(“<h2>Has accedido a este servlet “ + con-
tadorAccesos + “ veces es esta sesión.</h2>”);
out.println(“<p>El identificador de la sesión es “ +
session.getId() + “)</p>”);

out.println(“<p>La sesión fue creada en “ +


new Date(session.getCreationTime()) + “)</p>”);
out.println(“<p>Esta sesión fue accedida por última
vez el “ +
new Date(session.getLastAccessedTime()) + “)</
p>”);
out.println(“<p>El intervalo máximo de inactividad
de la sesión es “ + session.getMaxInactiveInterval() + “segun-
dos)</p>”);

out.println(“<p><a href=’” + request.getRequestURI()


+ “’>Refrescar</a></body></html>”);
} finally {
out.close();
}
}

140
3: Desarrollo con Servlets y Java Server Pages

@Override
protected void doGet(HttpServletRequest request, HttpServ-
letResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServ-
letResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
public String getServletInfo() {
return “Short description”;
}// </editor-fold>
}
Figura 3.21.  Código fuente de SessionServlet.java.

El resultado será una página HTML en la que se puede visualizar que el número de
accesos se incrementa conforme accedemos al enlace “Refrescar”. Cabe resaltar las
anotaciones que aparecen encima del nombre de la clase ya que, gracias a ellas
podremos obviar la declaración del servlet en el archivo web.xml.

Figura 3.22.  Resultado de la ejecución de SessionServlet.

3.3.8.  Ejemplo: mi primer Servlet


Hasta aquí hemos hecho un repaso bastante completo sobre toda la teoría del API
de Servlets. El alumno posee ya instrumentos suficientes como para desarrollar una
primera aplicación web sencilla usando el anterior proyecto, UD3WebApp, con un
servlet ResumenServlet.java que contiene un resumen de todo lo visto.

El código fuente se incluye a continuación:

141
Desarrollo de aplicaciones Web con Java EE

package com.seas.ud3.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ResumenServlet extends HttpServlet {

static private String param1;


static private String param2;
private String contextAtt1;
private String contextAtt2;
private String contextAtt3;

protected void processRequest(HttpServletRequest request, HttpSer-


vletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet EjemploServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Servlet <i>” + request.getServletPath() + “</i> de la
Aplicación <i>” + request.getContextPath() + “</i></h1>”);
out.println(“Hoy es <i>” + new Date() + “</i>”);
out.println(“<p>Método HTTP: <i>” + request.getMethod() + “</i></p>”);
out.println(“<p>URI solicitada: <i>” + request.getRequestURI() + “</i></p>”);
out.println(“<p>Protocolo: <i>” + request.getProtocol() + “</i></p>”);
out.println(“<p>Codificación de caracteres: <i>” + request.getCharacte-
rEncoding() + “</i></p>”);
out.println(“<p>Dirección IP remota: <i>” + request.getRemoteAddr() +
“</i></p>”);
out.println(“<p>Un número aleatorio: <strong><i>” + Math.ran-
dom() + “</i></strong></p>”);
out.println(“<p>VALORES DE INICIALIZACIÓN DE LA APLICACIÓN
(ServletConfig).</p>”);

142
3: Desarrollo con Servlets y Java Server Pages

out.println(“<p><strong>Parametro 1: <i>” + param1 + “</i></


strong></p>”);
out.println(“<p><strong>Parametro 2: <i>” + param2 + “</i></
strong></p>”);
out.println(“<p>VALORES DE INICIALIZACIÓN DEL SERVLET (Ser-
vletContext):</p>”);
out.println(“<p><strong>DatabaseURL: <i>” + contextAtt1 + “</
i></strong></p>”);
out.println(“<p><strong>UserDB: <i>” + contextAtt2 + “</i></
strong></p>”);
out.println(“<p><strong>PasswordDB: <i>” + contextAtt3 + “</
i></strong></p>”);
out.println(“</body>”);
out.println(“</html>”);
} finally {
out.close();
}
}
@Override
public void init(ServletConfig config) throws ServletException {

super.init(config);
ResumenServlet.param1 = getInitParameter(“Proveedor”);
ResumenServlet.param2 = getInitParameter(“Contacto”);
ServletContext context = config.getServletContext();
contextAtt1 = context.getInitParameter(“DatabaseURL”);
contextAtt2 = context.getInitParameter(“UserDB”);
contextAtt3 = context.getInitParameter(“PasswordDB”);
}

@Override
protected void doGet(HttpServletRequest request, HttpServletRes-
ponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletRes-
ponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
public String getServletInfo() {
return “Short description”;
}

143
Desarrollo de aplicaciones Web con Java EE

}
Figura 3.23.  Codigo fuente de ResumenServlet.java.

El resultado de su invocación en la URL http://localhost:8080/<Proyecto>/


ResumenServlet se muestra en la siguiente figura. Deberemos completar el archivo
web.xml con las estructuras XML vistas anteriormente en esta unidad para obtener los
valores concretos que se muestran.

Figura 3.24.  Resultado de la ejecución de ResumenServlet para el proyecto UD3WebApp.

144
3: Desarrollo con Servlets y Java Server Pages

EJERCICIO PROPUESTO
Para reforzar los conceptos introducidos hasta aquí se recomienda al alum-
no realizar esta sencilla práctica.
Crea un proyecto en NetBeans para una aplicación web que sirva para re-
coger encuestas a los alumnos de un curso con el título “Desarrollo web con
Servlets”. Para ello, la aplicación debe contener un servlet que recoja los
datos de un formulario con los siguientes campos:
■■ Campo de texto “Nombre del alumno”.
■■ Campo de password “Password del alumno”.
■■ Lista desplegable “Edad de alumno”.
■■ Botones de selección “Sexo” con valores posibles “Hombre” o “Mujer”.
■■ Lista desplegable “Nivel de estudios” con los siete valores posibles:
graduado escolar, bachillerato, grado medio, grado superior, diplomado,
licenciado/ingeniero, master.
■■ Apartado “Conocimientos previos” con los siguientes check-box dis-
ponibles: Java básico (Java SE), C, C++, C#, ObjectiveC, Cobol y PHP.
■■ Lista desplegable “Valora el material del curso” con valores del 1 al 10.
■■ Lista desplegable “Nivel de satisfacción con los conocimientos adqui-
ridos en el curso” con valores del 1 al 10.
■■ Área de texto “Comentarios”.
El servlet se encargará de recoger esta información y de presentar al alumno
una página HTML que contenga la siguiente información:
■■ Damos las gracias al usuario que ha realizado la encuesta.
■■ Se informa al usuario de que su email solo será utilizado como medio
de contacto para darle más información sobre el curso y feedback por
sus comentarios.
■■ Se presenta la información introducida en modo texto.
Además recomendamos al usuario, que al implementar su servlet tenga en
cuenta estas reflexiones:
■■ ¿Qué pasa si el alumno introduce una edad no válida? Ej., caracteres
alfabéticos en lugar de numéricos.
■■ ¿Cómo puede verificarse que lo realmente introducido en el campo del
email es una dirección de correo electrónico válida?
■■ ¿Qué pasa si el usuario deja en blanco alguno de los campos?
Y que tenga presente la teoría acerca de etiquetas HTML como <input>
y su atributo type o <form>.

El formulario tendrá un aspecto base similar al mostrado a continuación.

145
Desarrollo de aplicaciones Web con Java EE

Figura 3.25.  Formulario a implementar como actividad recomendada.

Podrá completarse con algunos datos ficticios como los mostrados a continuación:

146
3: Desarrollo con Servlets y Java Server Pages

Figura 3.26.  Introducción de datos en un formulario de ejemplo.

Y cuando pulsemos el botón “ENVIAR”, la aplicación presentará los datos recogidos


por el formulario en una página como la siguiente:

147
Desarrollo de aplicaciones Web con Java EE

Figura 3.27.  Datos recogidos por el formulario.

En la figura anterior podemos ver como se muestran de manera incorrecta algunos


caracteres. Para solucionar esto podemos añadir al proyecto un descriptor de
glassfish (glassfish-web.xml). Dentro de este archivo, inmediatamente dentro del
nodo <glassfish-web-app> especificaremos la codificación que utilizará el servidor
para el envío de parámetros mediante:

<parameter-encoding default-charset=”UTF-8”/>

148
3: Desarrollo con Servlets y Java Server Pages

3.4.  Java Server Pages (JSPs)


Hasta aquí hemos visto qué es un servlet, conocemos su ciclo de vida y hemos
profundizado en las clases e interfaces más relevantes de su API. Con todos estos
conocimientos, entender qué son las Java Server Pages, o en adelante para abreviar
JSPs, será mucho más sencillo.

Puede decirse que las JSP son también Servlets, solo que tienen forma de plantilla
para focalizar el esfuerzo del desarrollador más en la interfaz gráfica diseñada con
HTML, que en el código Java.

La siguiente figura muestra gráficamente cómo es el proceso de desarrollo de una


página JSP desde que el desarrollador la escribe hasta que existe una instancia creada
del servlet asociado a la JSP.

Figura 3.28.  Proceso de desarrollo de una página JSP.

El contenedor de servlets también tiene un papel esencial en la gestión de páginas JSP,


ya que la traducirá y la convertirá a servlet durante la fase de compilación. De hecho,
al igual que en un servlet, asociado a una JSP existen instancias de los objetos como
HTTPRequest, HTTPResponse, HTTPSession, y podrán ser invocados sin definirlos a
través de las variables request, response y session, respectivamente.

3.4.1.  Embebiendo sentencias Java en una JSP


En una JSP puede embeberse código Java a través de 4 mecanismos distintos:

■■ Scriptlets: sirven para incluir sentencias java comunes acotadas por los símbolos
<% %>. El código así escrito es insertado dentro del método service() del
servlet vinculado a la JSP.

■■ Expresiones: son acotadas a través de los símbolos <%= … %>. En tiempo de


ejecución el valor de la expresión es calculado e insertado en la salida del JSP.

■■ Declaraciones: para declarar valores de variables se utilizan <%! … %>. El código


declarado de esta manera formará parte del método service() en el servlet
asociado a la JSP. En cuanto a las variables aquí declaradas, serán compartidas
por todos los hilos vinculados a la instancia del servlet en el contenedor web. Es
por tanto necesario utilizar métodos sincronizados para acceder a ellas.

■■ Directivas: se utilizan los símbolos <%@ … %>. Típicamente se utilizan para


incluir información especial como sentencias import o definición de parámetros
de la página HTML resultante de la ejecución. Existen dos tipos de directivas:
page e include.

149
Desarrollo de aplicaciones Web con Java EE

□□ page: las directivas de este tipo más habituales se resumen en la siguiente


tabla:

Directiva page Ejemplo de uso


import <%@ page import=”java.util.*” %>
contentType <%@ page contentType=”text/plain” %>
session <%@ page session=”true” %>

El valor por defecto es true, y con valor false se indica que no se están utilizando
sesiones.
errorPage <%@ page errorPage=”/404.html” %>
isErrorPage <%@ page isErrorPage=”false” %>

Se utiliza true para indicar que sí existe una página de error. False es el valor por
defecto, que indica que no existe página de error.
isThreadS- <%@ page isThreadSafe=”false” %>
afe
El valor false indicará que el servlet asociado debe implementar el modelo Sin-
gleThreadModel, para así tener diferentes instancias para gestionar cada petición
simultánea. Recuerda que usar esta caracterísitca tiene un gran impacto sobre la
latencia de la aplicación web, por ello su valor por defecto es true.
extends <%@ page extends=”com.seas.ClasePadre” %>
info <%@ page info=”Nombre de la JSP” %>

Este String será devuelto a través del método getServletInfo().

include: estas directivas se utilizan para incluir las rutas a otros ficheros,
normalmente tipo jsp, pero también HTML con cabeceras, pies de páginas,
etc., para que su código sea embebido en la página resultante en el servidor.

3.4.2.  Sintaxis XML para JavaServer Pages


A partir de la versión 1.2 de la especificación de JavaServer Pages se incluye la
posibilidad de construir las JSP como documentos XML, refiriéndonos a ellos entonces
como documentos JSP. Esto se hizo para que una JSP fuera capaz de generar
contenido adicional al HTML tradicional, debido principalmente al auge de nuevos
lenguajes basados en XML como XHTML o SVG, así como en el uso extendido de
servicios web.

Hasta entonces un fichero JSP tenía casi el aspecto de un documento XML, pero
la inserción de scriptlets alteraba considerablemente el código y lo enmarañaba
demasiado. Se define entonces una nueva etiqueta <jsp:> que será utilizada como
base para normalizar el documento JSP. Pero fue realmente en la especificación 2.0
de JSP cuando se formalizan las definiciones para conseguir así mover JSP hacia una
sintaxis de tipo XML.

150
3: Desarrollo con Servlets y Java Server Pages

En un documento JSP pueden utilizarse las siguientes etiquetas o tags:

■■ Tags estándar JSP: están identificadas por el valor <jsp:>, con lo que la
apariencia del código embebido se estructura como en un documento XML, sin
alterar demasiado el orden de la página. Por ejemplo:

□□ Para declarar sentencias java: <jsp:setProperty name=”admin”


property=”usuario” value=”admin” />
□□ Scriptlets: <jsp:scriplet> . . . </jsp:scriplet>
□□ Expresiones: <jsp:expression> expresion </jsp:expression>
□□ Declaraciones: <jsp:declaration> declaration </jsp: declaration>
□□ Directivas: <jsp:directive.page attribute=”value” />
□□ … y hay muchas más que se verán en detalle más adelante.

■■ Tags personalizadas (custom) JSP: son etiquetas a medida que se definirán


de forma separada a la JSP y serán declaradas para su uso en el documento
a través de la directiva <%@ taglib >. Se trata de un concepto avanzado,
con lo que no las utilizaremos en este curso, si bien, el alumno interesado puede
consultar la especificación JSP 2.1 para obtener más información.

■■ JavaServer Tags Language (JSTL): se definen a partir de la versión 2.1 de


JSPs y son un conjunto de librerías de tags. Su uso facilita enormemente el
desarrollo de las aplicaciones. La actual versión en vigor es la 1.2 y en apartados
posteriores se profundizará en ella.

3.4.3.  Objetos implícitos en JSPs


El contenedor de servlets, en el proceso de traducción de JSP a servlet será el
responsable de crear objetos implícitos vinculados a un servlet. Así, en la fase de
escritura de una JSP el desarrollador podrá hacer uso a esos objetos sin necesidad de
incluirlos en la declaración de variables. Existen nueve objetos implícitos.

■■ application de tipo javax.servlet.ServletContext.

Representa el objeto ServletContext que es compartido en toda la aplicación


web. Se vió el detalle de su uso en la sección anterior de servlets.

■■ config de tipo javax.servlet.ServletConfig.

Al tratarse de una instancia de ServletConfig, su uso es exactamente el


mismo que fue expuesto en la sección 3.3.5 de esta unidad, con la diferencia de
que aquí podrán configurarse los parámetros de inicialización incluidos bajo la
etiqueta <jsp-file> dónde se declaran las JSPs de la aplicación web en web.
xml. A través del método getInitParameter(String name) de este
objeto podrá accederse a los parámetros declarados.
■■ exception de tipo java.lang.Throwable.
Este objeto tiene un ámbito local a cada JSP y sirve para redireccionar a las
páginas de error JSP.

151
Desarrollo de aplicaciones Web con Java EE

■■ out de tipo javax.servlet.jsp.JspWriter.


El uso de este objeto da acceso al stream de salida del servlet generado por el
contenedor.
■■ page de tipo java.lang.Object.
Este objeto representa una instancia del objeto servlet al que es traducida la JSP
que lo contiene.
■■ pageContext de tipo javax.servlet.jsp.PageContext.
Este objeto tiene un contexto local y da acceso a una API desde la que gestionar
atributos propios como tags personalizadas.
■■ request de tipo javax.servlet.ServletRequest.
Este objeto da acceso típicamente a la petición HTTPServletRequest a
través del método service() de la clase servlet vinculada a la JSP, y que en este
caso se denomina _jspService().
■■ response de tipo javax.servlet.ServletResponse.
De forma equivalente al objeto implícito request, response representa la petición
HTTPServletResponse.
■■ session de tipo javax.servlet.http.HttpSession.
Es la instancia del objeto HTTPSession que persiste a lo largo de toda la
sesión del usuario.

3.4.4.  Creando JavaServer Pages con NetBeans


Vamos a ilustrar a continuación cómo añadir nuestras propias páginas JSP a nuestra
aplicación web de ejemplo. Sobre la vista de proyecto, y en el directorio web, pulsamos
con el botón derecho sobre “New → JSP”, Tal y como se indica en la figura.

Figura 3.29.  Creación de página JSP en una aplicación web en NetBeans.

152
3: Desarrollo con Servlets y Java Server Pages

Accedemos a un cuadro de diálogo donde podemos configurar diferentes propiedades


del archivo, tal y cómo se muestra en la figura 3.32.

■■ Nombre del fichero.

■■ Localización en la estructura de directorios: típicamente bajo Web Pages.

■■ Carpeta dentro del directorio “Location”. Esto suele hacerse cuando el proyecto
tiene un tamaño considerable, y se han estructurado las JSPs de acuerdo a
criterios de funcionalidad, por ejemplo. En nuestro caso dejaremos este cuadro
de texto vacío.

■■ Opciones de creación: existen dos opciones: fichero JSP con sintaxis estándar
o bien documento JSP con sintaxis XML. Seleccionamos en nuestro caso la
primera opción.

Figura 3.30.  Selección de opciones de la nueva JSP.

153
Desarrollo de aplicaciones Web con Java EE

Aquí es interesante incluir una referencia. Desde la especificación 2.0 de


JSP, éstas pueden construirse de dos formas:
■■ Con formato, en cuyo caso la extensión del archivo será .jsp. Estas
serán el tipo de páginas que desarrollemos en esta parte del curso.
■■ Como documentos XML, siendo el archivo generado de extensión
.jspx. Dentro de estos documentos, podrán embeberse fragmentos JSP
con extensión .jspf. En este tipo de documentos no se deberán insertar
fragmentos tipo scriptlet, sino que deberán incluirse tags JSP, para res-
petar una sintaxis tipo XML.

NetBeans creará la estructura de una JSP sencilla que podrá ser completada por el
desarrollador.

<%@page contentType=”text/html” pageEncoding=”UTF-8”%>


<!DOCTYPE html>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8”>
<title>JSP Page</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
Figura 3.31.  Esquema simple de JSP generado por NetBeans.

Si lo que hemos creado es un documento XML, entonces el esquema que NetBeans


nos ofrece es el siguiente:

<jsp:root xmlns:jsp=”http://java.sun.com/JSP/Page” version=”2.0”>


<jsp:directive.page contentType=”text/html” pageEncoding=”UTF-8”/>
<!-- any content can be specified here, e.g.: -->
<jsp:element name=”text”>
<jsp:attribute name=”lang”>EN</jsp:attribute>
<jsp:body>Hello World!</jsp:body>
</jsp:element>
</jsp:root>
Figura 3.32.  Esquema de documento JSP generado por NetBeans.

En ambos casos, una vez desplegada la aplicación web en el servidor, podrá ejecutarse
a través de las URL:

■■ http://localhost:8080/<Proyecto>/MiPrimerJSP.jsp para la
página JSP y

■■ http://localhost:8080/<Proyecto>/MiPrimerDocJSP.jsp para el
documento JSP.

154
3: Desarrollo con Servlets y Java Server Pages

3.4.4.1.  Editando archivos HTML


NetBeans es un IDE orientado a trabajar en entornos Java y aunque permite la edición
de otro tipo de archivos que forman parte de la aplicación web, es cierto que quizá
no proporciona un entorno muy amigable para por ejemplo, editar complejos archivos
HTML que sirven de base para la creación de JSPs. Si bien no es el objetivo del curso,
si es recomendable que el alumno se familiarice con las etiquetas HTML y sea capaz
de diseñar páginas sencillas desde este IDE.

Para diseños más complejos podría ser aconsejable el disponer de un editor de


archivos HTML/CSS/JS que faciliten el trabajo con este tipo de ficheros, al menos en
una primera fase de diseño de la parte gráfica de nuestras aplicaciones web.

A continuación damos una lista de editores gratuitos de este tipo para que el alumno
pueda escoger el que más le convenga.

■■ NVU. Se trata de un proyecto opensource que dio origen a NVU y Blue Griffon.
Puede accederse a más información desde su site oficial: http://net2.com/nvu/
index.html.

■■ KOMPOZER. Se trata de un proyecto surgido para corregir algunos de los bugs


detectados en NVU. El site oficial es http://kompozer.net/ y la última versión
estable durante la redacción de este curso es la 0.7.10, y data de 2007. Y es que
este proyecto ha ido perdiendo terreno en favor Blue Griffon.

■■ BLUE GRIFFON. Es un editor de texto y gráfico que soporta diferentes formatos


gráficos como HTML, HTML 5, CSS 3, SVG, etc. La versión estable en el
momento de la redacción de este curso es la 1.5.2, y puede descargarse desde
el sitio web el proyecto: http://bluegriffon.org

155
Desarrollo de aplicaciones Web con Java EE

■■ BRACKETS. Es un editor opensource desarrollado por Adobe y distribuido bajo


licencia MIT. Su página oficial es htt://brackets.io. En la fecha de redacción de este
manual, la última versión estable que se estaba distribuyendo se corresponde
con la versión Sprint 13. Cualquiera de ellas está accesible desde este site:
https://github.com/adobe/brackets/downloads

Actualmente no es un editor fiable para el uso, pero dado que se trata de un


proyecto apadrinado por Adobe, posee un gran potencial de desarrollo. Como
visualizador de archivos utiliza Google Chrome.

Desde este curso recomendamos utilizar Blue Griffon. Actualmente es el


más versátil y estable de todos. Si bien, destacamos que es altamente im-
portante conocer el significado de las etiquetas HTML y sus atributos, que
son utilizados en el desarrollo de páginas web. La razón está en que este
tipo de editores gráficos, tanto opensource como comerciales, suelen incluir
tags en ocasiones innecesarias y que a veces complican bastante la lectura
de la página.

3.4.4.2.  Ejemplo: mi primer JSP


A continuación vamos a crear una JSP que servirá para tratar y representar al usuario
los datos recogidos a través de un formulario. Tomaremos como referencia el formulario
creado en la práctica propuesta en el apartado [3.3.8 - Ejemplo: mi primer Servlet].

El JSP que vamos a crear, de nombre FormularioJSP, como es habitual, sustituye


en realidad al servlet del ejemplo anterior.

156
3: Desarrollo con Servlets y Java Server Pages

Figura 3.33.  Wizard para crear un nuevo JSP en nuestro proyecto en NetBeans.

De esta forma contaremos con un fichero Formulario.html que muestre el


formulario con todas sus opciones, y FormularioJSP.jsp recogerá los datos (esto
se especifica mediante el atributo action de la etiqueta <form>) y los presentará
por pantalla.

Para aquellos alumnos que todavía no posean un dominio de las etiquetas HTML
como para editar directamente una interfaz gráfica, pueden utilizar BlueGriffon para
crear una plantilla que sirva de base para la JSP final. Aquí la creatividad de cada uno
juega un papel importante, podemos simplemente partir de algo como lo que muestra
la siguiente figura:

157
Desarrollo de aplicaciones Web con Java EE

Figura 3.34.  Presentación de la información recogida con el formulario.

El programa BlueGriffon genera automáticamente el código HTML que deberemos


incluir como base en nuestra JSP. Sobre este código sustituiremos las palabras
escritas en morado de la pantalla anterior por los valores obtenidos del formulario, de
forma análoga a cómo se hizo en el servlet del primer ejemplo.

La siguiente tabla muestra a modo de ejemplo el código fuente incluido para cada uno
de los campos del formulario.

158
3: Desarrollo con Servlets y Java Server Pages

Valor a incluir Código fuente embebido en FormularioJSP.jsp


nombre <%= request.getParameter(“nombre”) %>
Contraseña <%= request.getParameter(“password”) %>
<%
String sexo = request.getParameter(“sexo”);
String msgSexo= ””;
if (sexo == null) {
msgSexo = “VACÍO”;
} else if (sexo.equals(“h”)) {
Sexo
msgSexo = “HOMBRE”;
} else {
msgSexo = “MUJER”;
}
%>
<%= msgSexo %>
<%
String edad = request.getParameter(“edad”);
String msgEdad = “”;
if (edad == null) {
msgEdad = “VACÍO”;
} else if (edad.equals(“1”)) {
msgEdad = “&lt; 18 años”;
} else if (edad.equals(“18”)) {
msgEdad = “Edad entre 18 y 25 años”;
} else if (edad.equals(“26”)) {
Edad
msgEdad = “Edad entre 26 y 35 años”;
} else if (edad.equals(“36”)) {
msgEdad = “Edad entre 36 y 45 años”;
} else if (edad.equals(“46”)) {
msgEdad = “Edad entre 46 y 65 años”;
} else {
msgEdad = “Edad &gt; 65 años”;
}
%>
<%= msgEdad %>

159
Desarrollo de aplicaciones Web con Java EE

Valor a incluir Código fuente embebido en FormularioJSP.jsp


<%
String estudios = request.
getParameter(“estudios”);
String msgEstudios = “”;
if (estudios == null) {
msgEstudios = “VACIO”;
} else if (estudios.equals(“1”)) {
Estudios
msgEstudios = “GRADUADO ESCOLAR”;
} else if (estudios.equals(“2”)) {
msgEstudios = “BACHILLERATO”;
} else if (estudios.equals(“3”)) {
msgEstudios = “GRADO MEDIO”;
} else if (estudios.equals(“4”)) {
msgEstudios = “GRADO SUPERIOR”;
} else if (estudios.equals(“5”)) {
msgEstudios = “DIPLOMADO”;
} else if (estudios.equals(“6”)) {
msgEstudios = “LICENCIADO / INGENIERO”;
} else if (estudios.equals(“7”)) {
msgEstudios = “POSTGRADO / MASTER”;
} else {
msgEstudios = “ESTUDIOS SIN DETERMINAR”;
}
%>
<%= msgEstudios %>

160
3: Desarrollo con Servlets y Java Server Pages

Valor a incluir Código fuente embebido en FormularioJSP.jsp


<%
String[] lenguajes = request.
getParameterValues(“lenguaje”);
String msgLenguaje = “”;
if (lenguajes == null || lenguajes.length == 0) {
msgLenguaje = “NINGUNO”;
} else {
Lenguajes
for (String lenguaje : lenguajes) {
if (lenguaje.equals(“java”)) {
msgLenguaje += “Java “;
} else if (lenguaje.equals(“c”)) {
msgLenguaje += “C “;
} else if (lenguaje.equals(“c++”)) {
msgLenguaje += “C++ “;
} else if (lenguaje.equals(“cs”)) {
msgLenguaje += “C# “;
} else if (lenguaje.equals(“objectivec”)) {
msgLenguaje += “ObjectiveC “;
} else if (lenguaje.equals(“cobol”)) {
msgLenguaje += “Cobol “;
} else if (lenguaje.equals(“php”)) {
msgLenguaje += “PHP “;
}
}
}
%>
<%= msgLenguaje %>
Valoración
<%= request.getParameter(“materiales”) %>
materiales
Valoración curso <%= request.getParameter(“curso”) %>
<%
String comentarios =
request.getParameter(“comentarios”);
String msgComentarios = “”;
if (comentarios == null
Comentarios
|| comentarios.equals(“Introduce aquí tus comentarios...”)) {
msgComentarios = “No hay comentarios.”;
} else {
msgComentarios = comentarios;
}
%>
<%= msgComentarios %>

Figura 3.35.  Lista de parámetros recogidos en el formulario de FormularioJSP.jsp.

161
Desarrollo de aplicaciones Web con Java EE

EJERCICIO PROPUESTO
Vamos a profundizar en el ejemplo propuesto para hacerlo más exhaustivo
de acuerdo al patrón de diseño Modelo-Vista-Controlador (MVC). Para ello
se propone lo siguiente:
■■ Crea una clase de tipo bean, por ejemplo DatosEncuestaBean.
java, que represente los valores aportados por cada alumno en el
formulario de satisfacción del curso.
■■ Modifica tu FormularioJSP.jsp para que obtenga los valores
de un objeto de tipo DatosEncuestaBean que sea pasado como
parámetro por alguno de los objetos asociados al JSP.
Reflexiona sobre lo siguiente:
■■ ¿Será necesario crear alguna clase adicional para gestionar la repre-
sentación gráfica de los datos?
■■ ¿Piensas que este paso es innecesario o por el contrario aporta algo
positivo al diseño de tu web? ¿Por qué?

3.4.5.  Expression Language 2.1


El lenguaje de expresión, o más habitualmente utilizado con el acrónimo en inglés EL
fue desarrollado a partir de la inspiración de lenguajes de script como ECMAScript
(javascript) y XPath. De hecho, como en los lenguajes de script, las expresiones en EL
también son evaluadas en tiempo de ejecución.

Desde su nacimiento junto con la versión 1.2 de las JSP ha seguido usándose, si bien
no posee una JSR propia que lo defina, y sus versiones van actualizándose de forma
paralela a las de JSP. La versión actual es la 2.1.

Las expresión en EL tiene el formato ${expresion} o de forma equivalente


#{expresion}, que es la utilizada en JSF (se verá más adelante). A partir de aquí, las
características más relevantes del lenguaje de expresión se enumeran a continuación:

■■ Las expresiones pueden incluir valores literales, variables o variables implícitas.


La siguiente tabla muestra la forma de referirnos a algunos de esos objetos
implícitos de las JSPs y lo que representan:

162
3: Desarrollo con Servlets y Java Server Pages

Objeto implícito Descripción


${pageContext} Representa el objeto pageContext.

${pageScope} Es un objeto tipo Map que mapea nombres de atributos page-scope y


sus valores.

${requestScope} Es un objeto tipo Map que incluye las parejas nombre-valor de los atribu-
tos del objeto request.

${sessionScope} Objeto tipo Map que incluye las parejas nombre-valor de los atributos del
objeto session.

${applicationScope} Objeto tipo Map que incluye parejas de atributos nombre-valor de la


aplicación.
Objeto tipo Map que incluye atributos como parejas de nombres y valores
${param} de parametros de petición HTTP. Solo contiene el primer valor para cada
nombre.

${paramValues} Objeto tipo Map que asocia nombres de parámetros a un array de Strings
con sus valores posibles.
${header} Mapa de asociaciones entre nombres de cabeceras y sus valores.

${headerValues} Mapa de asociaciones entre nombres de cabeceras y arrays de string


con todos sus posibles valores.

${initParam} Mapa que incluye los nombres de los parámetros de inicialización y sus
valores.
${cookie} Mapa de cookies y sus valores.

Figura 3.36.  Referencias a variables implícitas de JSPs utilizando el Lenguaje de Expresión.

■■ Las expresiones aceptan todo tipo de operadores lógicos: ==, !=, div,
and, or, etc.

3.4.6.  Tags JSP


Hemos visto que la introducción del concepto documento JSP supone el nacimiento
de las tags JSP, y que además éstas pueden ser estándares o personalizadas (también
llamadas custom).

Las tags JSP introducen un nuevo elemento sintáctico denominado acciones que
sirven para proporcionar información en la fase de procesado de la petición. Dado
que las acciones son en realidad XML poseen las siguientes características generales:

■■ Podrán ser estándar o custom.

■■ Tendrán un tag de inicio y un tag final.

■■ Serán identificados por un nombre: <jsp:name>.

■■ Opcionalmente, podrán incluir atributos y un cuerpo.

163
Desarrollo de aplicaciones Web con Java EE

3.4.6.1.  Tags estándar


Las tags JSP estándar que representan acciones son las siguientes:

■■ <jsp:root>. Señala la raíz del documento con sintaxis XML. La existencia de


esta tag es única para todo el documento JSP.

■■ <jsp:useBean>. Es utilizado para crear o utilizar componentes JavaBeans


del tipo especificado desde la página.

■■ <jsp:setProperty>. Se utiliza para asignar valor a propiedades de los


JavaBeans declarados con la etiqueta <jsp:useBean>. Un ejemplo de su uso:

<jsp:useBean id=”curso” class=”com.seas.ud3.beans.Curso”>


<jsp:setProperty name=”curso” property=”titulo” value=”Java EE” />
<jsp:setProperty name=”curso” property=”proveedor” value=”SEAS” />
<jsp:setProperty name=”curso” property=”duracion” value=”150” />
</jsp:useBean>
Figura 3.37.  E jemplo de uso de las etiquetas <jsp:useBean> y <jsp:setProperty>.

■■ <jsp:getProperty>. Se utiliza para obtener el valor de propiedades de los


JavaBeans y asociarlo al objeto implícito out, de forma que pueda visualizarse
en la salida.

■■ <jsp:include>. Permite incluir recursos estáticos o dinámicos en el contexto


de la página y mostrarlos por la salida, a través de out.

■■ <jsp:forward>. Se utiliza con el atributo page para especificar la URL a la


que debe redirigirse una petición entrante.

■■ <jsp:param>. Se utiliza para proporcionar parejas de valores nombre/valor


de forma anidada a otras tags como <jsp:include> o <jsp:forward>.

■■ <jsp:plugin>. Permite embeber código fuente en la página jsp cuando es


necesario para visualizar correctamente el contenido, por ejemplo un applet.
Lleva asociados otras tags como <jsp:params> para especificar parámetros
del código fuente o <jsp:fallback> para detallar el mensaje que ha de
mostrarse cuando el contenido del plugin no puede ejecutarse.

■■ <jsp:body>. Esta acción permite definir el cuerpo de una acción, excepto


para la siguiente acción <jsp:invoke>.

■■ <jsp:invoke>. Solo puede usarse en ficheros de tags para incluir fragmentos


JSP que ayuden a la definición de etiquetas personalizadas.

■■ <jsp:doBody>. Al igual que la tag anterior, su uso solo es posible en ficheros de


tags.

■■ <jsp:element>. Esta acción se usa para generar elementos de forma


dinámica en el documento, típicamente elementos HTML que serán visualizados
como contenido final.

164
3: Desarrollo con Servlets y Java Server Pages

<jsp:element name=”td”>

<jsp:attribute name=”class”>celda</jsp:attribute>

<jsp:body>dato</jsp:body>

</jsp:element>
Figura 3.38.  Ejemplo de uso de la etiqueta <jsp:element>.

■■<jsp:attribute>. Permite definir el valor de un atributo de una acción en


el cuerpo del elemento XML en lugar en el de uno de sus atributos. También
permite especificar los atributos de un elemento que va a mostrarse por salida.

■■<jsp:text>. Esta acción sirve para embeber expresiones en EL o cualquier


información de forma que el documento siga siendo de tipo XML.

■■<jsp:output>. Usado solo en documentos JSP sirve para especificar cómo


es el tipo de contenido generado por el documento: por ejemplo el DOCTYPE.

Para poder utilizar tags personalizados, deberemos utilizar la directiva


<%@ taglib %> para insertar la ruta a los ficheros de tags.

3.4.6.2.  Definición y uso de tags custom


Normalmente durante la programación de nuestra aplicación, las tags estándar son
más que suficiente, pero en ocasiones puede ser útil definirnos ciertas tags en función
de nuestras necesidades para estructurar mejor y por tanto acelerar el proceso
de desarrollo. Esas serán tags personalizadas o custom, que deberán tener una
estructura de clases detrás encargadas de su procesamiento por parte del servidor de
aplicaciones. Estas clases incluyen métodos declarados como estáticos, tienen una
URL concreta y deben heredar y utilizar las clases del paquete java.servlet.jsp.
tagext.*. Cuando el compilador de JSP encuentre estas etiquetas, las sustituirá
por su código asociado y lo ejecutará.

Así, las custom tags son una herramienta muy potente pero su uso no es sencillo dado que
añaden una capa intermedia entre las páginas JSP y el servidor de aplicaciones.

Ejemplos típicos del uso de custom tags son las que permiten lógica java, código
en definitiva, del look-and-feel o la representación gráfica ofrecida por la página JSP,
como por ejemplo:

■■ Conversión de URLS: inclusión de rutas absolutas en recursos mostrados por


la JSP (imágenes, vídeos, archivos de estilos, etc.).

■■ Validación de datos que deben insertarse en una base de datos.

165
Desarrollo de aplicaciones Web con Java EE

■■ Generación de textos insertados en el look&feel en función de la evaluación


de datos codificados en una base de datos. Por ejemplo, si tenemos códigos
numéricos que identifican la titulación de una persona con valores del 0 al 100,
la traslación a texto puede hacerse a través de una custom tag.

■■ Generación automática de interfaces de usuario en varios idiomas.

■■ Etc.

En definitiva, en el uso de una librería de custom tags intervienen tres elementos:

■■ Una clase de tipo Tag Handler, que puede implementar el interfaz javax.
servlet.jsp.tagext.Tag o javax.servlet.jsp.tagext.BodyTag,
que incluye el código a ejecutar vinculado a las etiquetas.

■■ Un fichero de tipo *.tld (Tag Library Descriptor) que sirve para establecer la
correspondencia entre clases y etiquetas a través de elementos XML.

■■ Las páginas JSP que hacen uso de estas etiquetas e incluyen declaraciones de
tipo <%@taglib ... %> .

Detallamos a continuación el esquema general de esos tres elementos:

Declaración del fichero tipo TLD


Vamos a comenzar añadiendo el fichero de declaración de librería de etiquetas (.tld) en
nuestro ejemplo de aplicación web de NetBeans. Para ello sobre el proyecto clicamos
con el botón derecho “Nuevo” y buscamos entre las opciones el tipo “Tag Library
Descriptor”. Si no está en la lista seleccionamos “Other” y lo buscamos entre la lista
disponible, tal y como se muestra a continuación.

Figura 3.39.  Selección del descriptor TLD en el proyecto NetBeans de la aplicación web.

166
3: Desarrollo con Servlets y Java Server Pages

La página siguiente permite especificar el nombre y ruta al descriptor. Lo habitual es


mantener la ruta /WEB-INF/tlds para almacenar todos los descriptores de tantas
librerías custom definamos en la aplicación web. El resultado será la creación de una
nueva carpeta como se muestra en la siguiente figura.

Figura 3.40.  Descriptor mitaglibrary.tld añadido al proyecto en NetBeans.

NetBeans crea e incluye por defecto las etiquetas de cabecera del descriptor de
librerías, como se muestra a continuación:

<?xml version=”1.0” encoding=”UTF-8”?>

<taglib version=”2.1” xmlns=”http://java.sun.com/xml/ns/ja-


vaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.
sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd”>

<tlib-version>1.0</tlib-version>

<short-name>mitaglibrary</short-name>

<uri>/WEB-INF/tlds/mitaglibrary</uri>

</taglib>
Figura 3.41.  Descriptor TLD generado por defecto por NetBeans.

A esto deben añadirse etiquetas tipo <tag>. Cada una de ellas representa una
nueva custom tag con nombre, y clase vinculada que la implementa.

Definición de la clase Tag Handler


Para cada nueva tag que forme parte de nuestra librería, es necesario incluir un nuevo
elemento de tipo Tag Handler a través del menú Nuevo de nuestra aplicación web. Los
seleccionamos de la lista, como se muestra a continuación.

167
Desarrollo de aplicaciones Web con Java EE

Figura 3.42.  Añadir nueva clase de tipo Tag Handler.

En este ejemplo vamos a crear una nueva tag de nombre help que se encargará
de insertar mensajes de ayuda en nuestras JSP. Para ello creamos una clase
HelpHandler.java bajo el paquete com.seas.ud3.tags que extenderá el interfaz
BodyTagSupport, y que implementará la conversión de la url del recurso. Se
muestra a continuación el asistente de NetBeans.

Figura 3.43.  Asistente de NetBeans para incluir una clase de tipo Tag Handler.

168
3: Desarrollo con Servlets y Java Server Pages

En el último paso, NetBeans permite configurar de una forma gráfica la información


vinculada en el fichero descriptor TLD:

■■ Añadimos la información correspondiente en mitaglibrary.tld creado


previamente.

■■ Asignamos el nombre help a la nueva etiqueta.

■■ Nuestra etiqueta no requiere de cuerpo, por lo que marcamos la opción Body


Content en “empty”.

■■ Asignamos un atributo tipo int a la etiqueta, que se corresponderá con el código


del mensaje de ayuda a insertar en nuestra página web. Además su inclusión
al invocar a la etiqueta tiene carácter obligatorio y su valor será interpretado en
el momento de la invocación, por lo que “Request Time Evaluation” toma valor
“true”.

NetBeans generará una nueva clase HelpHandler.java con el siguiente código


fuente por defecto:
package com.seas.ud3.tags;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class HelpHandler extends BodyTagSupport {


private int code;

public HelpHandler() {
super();
}

private void otherDoStartTagOperations() { }

private void otherDoEndTagOperations() { }

private void writeTagBodyContent(JspWriter out, BodyContent bo-


dyContent) throws IOException {
bodyContent.writeOut(out);
bodyContent.clearBody();
}

public int doStartTag() throws JspException {


otherDoStartTagOperations();
if (theBodyShouldBeEvaluated()) {
return EVAL_BODY_BUFFERED;
} else {
return SKIP_BODY;
}
}

169
Desarrollo de aplicaciones Web con Java EE

public int doEndTag() throws JspException {


otherDoEndTagOperations();
if (shouldEvaluateRestOfPageAfterEndTag()) {
return EVAL_PAGE;
} else {
return SKIP_PAGE;
}
}

public int doAfterBody() throws JspException {


try {
BodyContent bodyCont = getBodyContent();
JspWriter out = bodyCont.getEnclosingWriter();
writeTagBodyContent(out, bodyCont);
} catch (Exception ex) {
handleBodyContentException(ex);
}
if (theBodyShouldBeEvaluatedAgain()) {
return EVAL_BODY_AGAIN;
} else {
return SKIP_BODY;
}
}

private void handleBodyContentException(Exception ex) throws


JspException {
throw new JspException(“Error in URLConverter tag”, ex);
}

private boolean shouldEvaluateRestOfPageAfterEndTag() {


return true;
}

private boolean theBodyShouldBeEvaluatedAgain() {


return false;
}

private boolean theBodyShouldBeEvaluated() {


return true;
}

public void setCode(int code) {


this.code = code;
}
}
Figura 3.44.  Código fuente de la clase HelpHandler.java.

170
3: Desarrollo con Servlets y Java Server Pages

El programador deberá completar los métodos que correspondan. Si lo que


buscamos es compatibilidad con la versión 4 de la plataforma Java, entonces nuestra
clase de tipo Tag Handler deberá heredar de javax.servlet.jsp.tagext.
SimpleTagSupport. En nuestro caso, utilizamos la última versión y heredamos de
javax.servlet.jsp.tagext.BodyTagSupport los siguientes métodos:

■■ Métodos de usuario: servirán para customizar el handler de la etiqueta.

□□ private void otherDoStartTagOperations():

El código contenido en este método es invocado después del método


doStartTag(), tras inicializar las variables de esta clase y antes de invocar
al método theBodyShouldBeEvaluated().

□□ private void otherDoEndTagOperations():

El código contenido en este método es invocado después del método


doEndTag(), tras inicializar las variables de esta clase y antes de invocar al
método shouldEvaluateRestOfPageAfterEndingTag().

□□ private void writeTagBodyContent(JspWriter out, BodyContent


bodyContent) throws IOException:

Este método solo se utiliza cuando la tag utilizada tiene cuerpo asociado, y
servirá para su procesamiento.

■■ Métodos del interfaz Tag Handler:

□□ public int doStartTag() throws JspException:

Este método se invoca cuando se encuentra el primer tag y después de él se


evaluarán los atributos si los hubiera en el body. Se recomienda no modificar
este método directamente, sino el método al que invoca.

□□ public int doEndTag() throws JspException:

Este método es llamado después de que la tag final ha sido procesada.

□□ public int doAfterBody() throws JspException:

Este método es invocado después de procesar el cuerpo de la etiqueta.

□□ private void handleBodyContentException(Exception ex)


throws JspException:

Este método trata cualquier excepción que se hubiera producido al tratar el


cuerpo de la etiqueta.

□□ private boolean shouldEvaluateRestOfPageAfterEndTag():

Este método debe implementarse si es necesario revisar el resto de la


página JSP después de haber ejecutado la etiqueta. Es invocado desde
doEndTag().

171
Desarrollo de aplicaciones Web con Java EE

□□ private boolean theBodyShouldBeEvaluatedAgain():

Este método debe implementarse si es necesario volver a revisar el cuerpo de la


etiqueta después de haberlo evaluado. Es llamado desde doAfterBody().

□□ private Boolean theBodyShouldBeEvaluated():

Este método debe implementarse si es necesario evaluar el cuerpo de la


etiqueta. Es invocado desde doStartTag().

□□ public void setCode(int code):

Este método asignará el código a la variable de la clase.

En etiquetas de uso simple, basta con tener en cuenta los métodos doStartTag() y
doEndTag(). Si se desea profundizar en el uso de estos métodos y otros adicionales de la
librería javax.servlet.jsp.tagext.*, revisar la especificación JSP 2.1.

En el descriptor TLD se incluirá un nuevo elemento tag con la siguiente información


vinculada a la etiqueta url:

<tag>

<name>help</name>

<tag-class>com.seas.ud3.tags.HelpHandler</tag-class>

<body-content>empty</body-content>

<attribute>

<name>code</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

<type>int</type>

</attribute>

</tag>

Figura 3.45.  Configuración de etiqueta url en el descriptor TLD.

Finalmente, modificaremos de acuerdo a nuestros requisitos el método doStartTag()


(o el invocado por este otherDoStartTagOperations()) con el siguiente código:
try {
JspWriter out = pageContext.getOut();
switch (this.code) {
case 1:
out.println(“MENSAJE DE AYUDA 1”);
break;

172
3: Desarrollo con Servlets y Java Server Pages

case 2:
out.println(“MENSAJE DE AYUDA 2”);
break;
case 3:
out.println(“MENSAJE DE AYUDA 3”);
break;
case 4:
out.println(“MENSAJE DE AYUDA 4”);
break;
default:
out.println(“MENSAJE DE AYUDA POR DEFECTO”);
break;
}

} catch (IOException ex) { }

Figura 3.46.  Lógica vinculada a la etiqueta custom help.

De esta forma, cualquier página JSP mostrará por pantalla el mensaje de ayuda
correspondiente codificado según una lista dada.

Utilización en páginas JSP


Para su utilización puede optarse por dos alternativas:

1. Inclusión de la referencia a la nueva librería de tags custom en el descriptor de


despliegue (o bien mediante la correspondiente anotación) para su posterior uso
directo en las JSPs dónde sea necesario.
<taglib>
<taglib-uri>/mitaglibrary</taglib-uri>
<taglib-location>
/WEB-INF/tlds/mitaglibrary.tld
</taglib-location>

</taglib>
Figura 3.47.  Declaración del uso de una librería de etiquetas custom.

2. O bien Uso directo en la jsp donde corresponda, omitiendo el paso anterior.


<%@taglib uri=”/WEB-INF/tlds/mitaglibrary.tld” prefix=”mitaglib”%>
. . .
<mitaglibrary:help code=”1” />
<mitaglibrary:help code=”2” />
<mitaglibrary:help code=”3” />
. . .
Figura 3.48.  Importación de una librería de etiquetas custom.

173
Desarrollo de aplicaciones Web con Java EE

3.4.7.  JSTL 1.1


En el apartado 3.4.6 de esta unidad hemos visto qué son las etiquetas JSP y que
existen dos tipos: estándar y custom. JSTL es el acrónimo de JSP Standard Tag
Library, es por tanto una librería de custom tags que ha sido estandarizada. En realidad
son cinco grupos de librerías:

■■ core: agrupa funciones script básicas como definición de condicionales, bucles


y comandos de entrada y salida de datos. Su prefijo es c.

■■ xml: para el procesamiento de documentos xml. Su prefijo es xml.

■■ fmt: para dar formato a monedas y fechas. Su prefijo es fmt.

■■ sql: para permitir el acceso a bases de datos a partir de sentencias SQL. Su


prefijo es sql.

■■ functions: para permitir la manipulación de cadenas y colecciones. Su prefijo es


fn.

Además, la librería JSLT permite referenciar a cualquier objeto de los objetos request,
response, o session de la JSP utilizando el esquema ${objeto.propiedad}.

A continuación se muestra un ejemplo de uso de la librería core. Obviamente, este


ejemplo, necesitará de una clase producto con los atributos nombre, unidades y
precio con sus métodos de acceso correspondientes y el constructor parametrizado.
<%@page import=”com.seas.ud3.beans.Producto” %>
<%@page contentType=”text/html” pageEncoding=”UTF-8”%>
<%@taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core” %>
<jsp:scriptlet>
Producto[] productos = new Producto[3];
productos[0] = new Producto(“Producto 1”, 1, 1.4f);
productos[1] = new Producto(“Producto 2”, 2, 2.4f);
productos[2] = new Producto(“Producto 3”, 3, 3.4f);
pageContext.setAttribute(“productos”, productos);
<jsp:scriptlet>

<!DOCTYPE html>
<html>
<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8”>


<title>EJEMPLO del uso de JSTL</title>
</head>
<body>
<h1>Productos almacenados en el array declarado en el
scriptlet:</h1>

174
3: Desarrollo con Servlets y Java Server Pages

<hr>
<table border=”1” width=”200”>
<tr>
<th>Nombre comercial</th>
<th>Unidades en stock</th>
<th>Precio unitario</th>
</tr>

<c:forEach var=”producto” items=”${productos}”>


<tr>
<td>${producto.nombre}</td>
<td>${producto.unidades}</td>
<td>${producto.precio}</td>
</tr>
</c:forEach>

</table>
<br />
<a href=”index.html”>Inicio</a>
</body>
</html>
Figura 3.49.  Código fuente con ejemplo de uso de la librería JSTL core.

Para poder utilizar una librería JSTL, es necesario especificar donde se encuentra su
especificación, equivalente a la sentencia import en java.

Para cada una de las librerías dicha sentencia es la siguiente:

■■ core: <%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core” %>

■■ fmt: <%@ taglib prefix=”fmt” uri=”http://java.sun.com/jsp/jstl/fmt” %>

■■ sql: <%@ taglib prefix=”sql” uri=”http://java.sun.com/jsp/jstl/sql” %>

■■ XML: <%@ taglib prefix=”x” uri=”http://java.sun.com/jsp/jstl/xml” %>

■■ functions: <%@ taglib prefix=”fn” uri=”http://java.sun.com/


jsp/jstl/functions” %>

3.4.8.  Configuración de web.xml para JSP


Hemos visto en la sección 3.3.4 del bloque de Servlets, alguna de las etiquetas más
relevantes que permiten definir los servlets de nuestra aplicación web, así como otros
elementos como parámetros de contexto, parámetros de inicialización de servlets o
configuración de páginas de inicio o error.

175
Desarrollo de aplicaciones Web con Java EE

Para las JavaServer pages es posible utilizar etiquetas específicas que vamos a
repasar a continuación:

■■ <jsp-file>: este elemento permite definir la ruta completa a un fichero


de tipo JSP dentro de una definición de <servlet>. La etiqueta <jsp-
file> se utiliza en lugar de la <servlet-class> y sirve para especificar el
archivo que representa al servlet. Como en la declaración de servlets, se utiliza
en combinación con <servlet-mapping> para especificar la ruta lógica al
fichero. Se muestra a continuación un ejemplo de uso.
<servlet>
<servlet-name>Formulario</servlet-name>
<jsp-file>/FormularioJSP.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Formulario</servlet-name>
<url-pattern>/EncuestaUsuarios</url-pattern>

</servlet-mapping>

Figura 3.50.  Declaración de una nueva JSP en el fichero web.xml.

Su valor siempre debe comenzar por la barra (/) cuando la JSP se encuentra
bajo el directorio raíz de la aplicación web como es el caso.

■■ <jsp-config>: esta etiqueta es el nodo raíz del que se encadenarán etiquetas


tipo taglib.

■■ <taglib>: este elemento determina la <taglib-uri> y <taglib-


location> para una librería custom de etiquetas JSP. Un ejemplo de uso es
el siguiente:
<jsp-config>
<taglib>
<taglib-uri>mitaglib</taglib-uri>
<taglib-location>/WEB-INF/jsp/mitaglib.tld</taglib-location>
</taglib>

</jsp-config>

Figura 3.51.  Ejemplo de declaración de librerías de etiquetas con <taglib>.

El valor del elemento <taglib-uri> puede ser también una dirección URL.

■■ <jsp-configType>: este elemento complejo permite definir la configuración


global de información relacionada con los ficheros de tipo JSP de la aplicación.
Bajo ella se incluyen los subelementos <taglib> y <jsp-property-
group>.

176
3: Desarrollo con Servlets y Java Server Pages

■■ <jsp-property-group>: estos elementos complejos sirven para incluir de


forma estática otros recursos (bien sean JSP, JSF) en una página concreta o en
un conjunto de páginas definidas a través de la etiqueta hija <url-pattern>
que queden fijos a modo de cabecera, a través del elemento <include-
prelude> o pie, a través del elemento <include-coda>. Es equivalente a
utilizar la directiva @include. A continuación se muestra un ejemplo de su uso.

<jsp-property-group>

<url-pattern>*.jsp</url-pattern>

<include-prelude>/WEB-INF/jsp/cabecera.jsp</include-prelude>

<include-coda>/WEB-INF/jsp/pie.jsp</include-coda>

</jsp-property-group>

Figura 3.52.  Ejemplo de uso de la etiqueta <jsp-property-group>.

177
Desarrollo de aplicaciones Web con Java EE

3.5.  Novedades de la especificación Servlets 3.0


La plataforma Java EE 6 y en concreto la especificación de Servlets 3.0 trae consigo
diferentes herramientas que facilitan la vida del programador. De entre ellas resalta una
nueva herramienta, las ANOTACIONES, que van a simplificar la programación. Las
principales novedades son las siguientes:

■■ Anotaciones como alternativa a la configuración de la aplicación web a través del


fichero tradicional web.xml.

■■ Nuevos aspectos de seguridad vinculados a los métodos de los servlets


configurados a través de anotaciones.

■■ Mecanismos de validación de beans a través de anotaciones.

■■ Procesado asíncrono de peticiones.

■■ Soporte de peticiones en formato mime/multipart para la subida de ficheros al


servidor.

En este curso, vamos a repasar las más relevantes para un programador que se
enfrenta por primera vez al desarrollo de aplicaciones web.

3.5.1.  Anotaciones
La especificación Servlet 3.0 recogida en la JSR-315 supone una revolución por
muchos motivos. Uno de ellos es que el descriptor de despliegue web.xml pasa a
convertirse en un elemento opcional. En su lugar, se incluye una nueva y potente
herramienta llamada anotaciones.

Las anotaciones son expresiones con la forma @XXX{} que incluyen fragmentos de
código que pueden incluirse tanto en el fichero .java que define un servlet como en
las JavaServer pages para definir información relacionada con la configuración de la
aplicación.

Las anotaciones solo serán procesadas e interpretadas por el servidor de


aplicaciones si las clases donde han sido definidas se encuentran bajo el
directorio WEB-INF/classes o si están en un archivo .jar bajo el directorio
WEB-INF/lib.

178
3: Desarrollo con Servlets y Java Server Pages

Las anotaciones existentes se definen en el paquete javax.servlet.annotation,


y a continuación se enumeran detallan y se ilustra con ejemplos sencillos su uso:

■■ @WebServlet: Esta anotación sirve para definir un nuevo servlet vinculado a la


aplicación web, así como sus datos más importantes. Las clases creadas con
esta anotación extienden la clase javax.servlet.http.HttpServlet.
Los parámetros que pueden definirse para ella son:

■■ name: nombre del servlet (opcional).

■■ asyncSupported: procesamiento síncrono (true) o asíncrono.

■■ largeIcon: icono grande asociado al servlet (opcional).

■■ smallIcon: icono pequeño asociado al servlet (opcional).

■■ description: descripción del servlet (opcional).

■■ initParams: array de parámetros de inicio, definidos bajo la anotación @


WebInitParam, que serán pasados a través de los parámetros de configuración
del servlet (opcional).

■■ loadOnStartup: valor entero que indica si el servlet será cargado desde la


activación de la aplicación o no (opcional).

■■ displayName: nombre que identifica al servlet (opcional).

■■ urlPatterns: array que incluye los patrones de las URL que permiten acceder
al servlet. Debe incluirse al menos un patrón.

A continuación se incluye un ejemplo de uso de esta anotación para definir los


parámetros de inicio del servlet EjemploServlet.
package com.seas.ud3.servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(asyncSupported = false, name = “EjemploServlet”,


urlPatterns = {“/Ejemplo”},
initParams = {
@WebInitParam(name = “Proveedor”, value = “SEAS”),
@WebInitParam(name = “Contacto”, value = “info@seas.es”)})

179
Desarrollo de aplicaciones Web con Java EE

public class EjemploServlet extends HttpServlet {

static private String param1;


static private String param2;
public void init(ServletConfig config) throws ServletException {
super.init(config);
EjemploServlet.param1 = getInitParameter(“Proveedor”);
EjemploServlet.param2 = getInitParameter(“Contacto”);
}

protected void processRequest(HttpServletRequest request, Http-


ServletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=UTF-8”);
PrintWriter out = response.getWriter();
try {
out.println(“<html>”);
out.println(“<head>”);
out.println(“<title>Servlet EjemploServlet</title>”);
out.println(“</head>”);
out.println(“<body>”);
out.println(“<h1>Parámetros de configuración del servlet “ +
request.getContextPath() + “</h1>”);
out.println(“<p>Parámetro 1: “ + EjemploServlet.param1 + “</p>”);
out.println(“<p>Parámetro 2: “ + EjemploServlet.param2 + “</p>”);
out.println(“</body>”);
out.println(“</html>”);
} finally {
out.close();
}
}
protected void doGet(HttpServletRequest request, HttpServletRes-
ponse response)
throws ServletException, IOException {
processRequest(request, response);
}

protected void doPost(HttpServletRequest request, HttpServle-


tResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

180
3: Desarrollo con Servlets y Java Server Pages

public String getServletInfo() {


return “Short description”;
}
}

Uso de @WebServlet para definir parámetros de inicialización del servlet. Esto es


equivalente a tener en el descriptor de despliegue lo siguiente:
<servlet>
<servlet-name>EjemploServlet</servlet-name>
<servlet-class>com.seas.EjemploServlet</servlet-class>
<init-param>
<param-name>Proveedor</param-name>
<param-value>SEAS Estudios Abiertos</param-value>
</init-param>
<init-param>
<param-name>Contacto</param-name>
<param-value>info@seas.es</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>EjemploServlet</servlet-name>
<url-pattern>/EjemploServlet</url-pattern>

</servlet-mapping>

Figura 3.53.  Declaración de parámetros de inicialización del servlet en web.xml.

■■ @WebFilter

Esta anotación sirve para definir una clase de tipo filtro dentro de la aplicación
web. Las clases que tienen esta anotación implementan el interfaz javax.
servlet.Filter.

Los parámetros que tiene asociados esta anotación son los siguientes:

□□ filterName: su valor por defecto, si no se especifica es el nombre de la clase


definida debajo.

□□ urlPatterns: array que incluye los patrones de las URL que permiten
acceder a la clase. Debe incluirse al menos un patrón.

□□ value: es equivalente al anterior. Debe utilizarse únicamente o urlPatterns


o value.

□□ asyncSupported: valor booleano, que como en el caso de @WebServlet,


indica si el Filtro soporta operar en modo síncrono (true) o asíncrono (false).

□□ dispatcherTypes: este elemento define el tipo de redirección de eventos


que puede gestionar el filtro (asíncrono, error, forward, include y request).

181
Desarrollo de aplicaciones Web con Java EE

□□ displayName: nombre del filtro que se visualiza.

□□ initParams: incluye una anotación de tipo @WebInitParams para indicar


la lista de parámetros del filtro.

□□ largeIcon: valor de una imagen grande vinculada al filtro.

□□ smallIcon: valor de una imagen pequeña, tipo icono, vinculada al filtro.

□□ servletNames: lista de nombres de Servlets para los que este Filtro está en uso.

Un ejemplo de su uso es el siguiente:


package com.seas.ud3.filters;
@WebFilter(filterName = “login”, urlPatterns = {“/login”},
initParams = {
@WebInitParam(name = “user”, value = “none”)})

public class LoginFilter implements Filter { . . . }

Ejemplo de uso de la anotación @WebFilter.

El API Servlets proporciona el interfaz Filter para realizar tareas previas a la


gestión de la petición HTTP. Los servlets implementan este interfaz para redirigir
las peticiones a clases externas que realicen tareas relacionadas con
la autenticación, generación de logs, encriptado, conversión de formatos
MIME, etc. Para más información puede consultarse el capítulo 6 “Filtering”
de la especificación del API Servlets 3.0 definida por la JSR-315.

■■ @WebInitParam: Esta anotación se utiliza para especificar los parámetros de


inicialización que se pasan al servlet o al filtro. Los atributos que puede incluir
son los siguientes:

□□ name: nombre del parámetro.

□□ value: valor del parámetro.

□□ description: descripción del parámetro de inicialización.

□□ Su uso ha quedado visto con anterioridad.

■■ @WebListener: Esta anotación sirve para definir diferentes tipos de listeners:

□□ Listeners de contexto como ServletContextListener.

□□ Listeners de atributos de contexto como ServletContextAttribute


Listener.

□□ Listeners de peticiones de servlet como ServletRequestListener.

182
3: Desarrollo con Servlets y Java Server Pages

□□ Listeners de atributos de peticiones de servlet como ServletRequest


AttributeListener.

□□ Listeners de sesión HTTP como HttpSessionListener.

□□ Listeners de atributos de sesión HTTP como HttpSessionAttribute


Listener.

Los eventos que escuchan estos listeners están relacionados normalmente con
la adición o borrado de atributos, o bien con la inicialización o destrucción de
parámetros.

■■ @MultipartConfig

Esta anotación se incluye previamente a la definición de un servlet cuando


se espera una petición de tipo mime/multipart. De esta forma el objeto
HttpServletRequest incluirá objetos tipo mime y podrá hacerse uso de los
métodos public Collection<Part>() getParts y public Part
getPart(String name) cuando sean demasiado grandes. Además permite
especificar aspectos como el máximo tamaño del archivo enviado, la ruta al
directorio donde se almacenan estos objetos, etc.

Los valores que permite definir esta anotación son los siguientes:

□□ location: marca la ruta absoluta a un directorio del sistema de ficheros


donde se almacenarán temporalmente los archivos enviados como parte de
la petición al servlet.

□□ fileSizeThreshold: este valor expresado en byte indica el tamaño máximo


del fichero que puede ser almacenado en disco.

□□ maxFileSize: este valor indica el valor máximo expresado en bytes que


pueden ocupar todos los ficheros almacenados. Si este valor se alcanza, el
contenedor de aplicaciones lanzará una excepción.

□□ maxRequestSize: este valor expresado en bytes indica el tamaño máximo


de la petición enviada al servidor.

Un ejemplo de uso de esta anotación es el siguiente:


@MultipartConfig(location=”/tmp”, fileSizeThreshold=1024*1024,
maxFileSize=1024*1024*5, maxRequestSize=1024*1024*5*5)

Figura 3.54.  Ejemplo de uso de la anotación @MultipartConfig.

183
Desarrollo de aplicaciones Web con Java EE

En la especificación Servlets 3.0 se incluye un nuevo atributo llamado me-


tadata-complete para el elemento raíz web-app del descriptor de des-
pliegue web.xml. Su valor es de tipo booleano:
■■ Si se establece en “true”, en el despliegue el servidor debe ignorar
cualquier anotación incluida en los ficheros de tipo .class, así como en
cualquier otro fragmento web.
■■ Si toma el valor “false”, en el despliegue deben examinarse todos
los archivos para interpretar y establecer lo definido por las anotaciones.

Hasta la especificación 3.0, la subida de ficheros al servidor desde aplica-


ciones web se realizaba utilizando librerías externas a la plataforma Java EE
que implementaban la especificación IETF RFC 1867 “Subida de ficheros en
HTML basada en formularios”. Con esta anotación se implementa en la pla-
taforma de forma estándar el mecanismo de subida de ficheros, pudiendo
especificarse además atributos como la localización del fichero o el tamaño
máximo permitido.

3.5.2.  Despliegue con web.xml y web-fragment.xml


Hemos visto que gracias a la definición de anotaciones en la especificación Servlet
3.0, la importancia del descriptor de despliegue web.xml se diluye, ya que su uso
pasa a ser opcional. Pero en el trabajo como programador podemos encontrarnos
con aplicaciones desarrolladas bajo Java EE versión 5, implementadas tomando una
versión de servlets anterior, por lo que es necesario conocer cuáles son las etiquetas
en el documento web.xml que tienen relación con la declaración y configuración
de las JSPs.

En otras ocasiones, el descriptor de despliegue puede utilizarse para sobrescribir la


configuración hecha con anotaciones. Esto puede ser útil durante el ciclo de desarrollo,
pruebas e integración de las aplicaciones, o por ejemplo al desplegar la aplicación
sobre cierto tipo de servidor de aplicaciones, donde se requiere una configuración
específica.

Además de estas dos opciones, la especificación Servlets 3.0 incluye una tercera vía a
través de lo que define como fragmentos web. Este concepto hace referencia a unos
segmentos de configuración encapsulados en un nuevo descriptor de despliegue
denominado web-fragment.xml, que también estará ubicado bajo la carpeta
META-INF/ del fichero war que se configura como desplegable.

También es posible que los fragmentos web formen parte de ficheros tipo .jar, y en este
caso el despliegue en el servidor de aplicaciones será responsable de revisar todos
ellos en busca de este tipo de archivos para aplicar los parámetros de configuración
que correspondan.

184
3: Desarrollo con Servlets y Java Server Pages

Orden en la configuración definida en web.xml y web-fragment.xml


¿Pero qué ocurre cuando dentro de una aplicación web nos encontramos con los dos
tipos de descriptores de despliegue y anotaciones? ¿Cuál de los tres mecanismos
tiene prioridad?

La mayor prioridad la tiene siempre y en caso de duda, el descriptor web.xml, por


ello se recomienda en desarrollo utilizarlo para asegurarnos una configuración clara
y estable. A partir de aquí, se pueden dar diferentes casuísticas que revisamos a
continuación de una forma básica y sencilla de comprender. Para un detalle más
profundo puede consultarse la sección 8.2.3 de la especificación Servlets 3.0.

Hemos visto que la forma de dar prioridad a anotaciones sobre ficheros de configuración
es a través del atributo metadata-complete. Si su valor es “true” no se tendrán
en cuenta ninguno de los ficheros de configuración, en caso contrario sí y habrá que
ver cómo se ordena su prioridad:

■■ <absolute-ordering>: esta etiqueta se incluye en el descriptor web.xml


para denotar la prioridad de web.xml frente a la lista detallada de fragmentos
web, web-fragment.xml incluida.

■■ <ordering>: si se encuentra esta etiqueta dentro de archivos tipo web-


fragment.xml, se realizará un orden relativo, según lo definido dentro gracias a
etiquetas como <before> y <after>.

De esta forma, si tenemos los siguientes fragmentos:

web-fragment.xml web-fragment.xml
<web-fragment> <web-fragment>
<name>Fragmento1</name> <name>Fragmento2</name>
<ordering> <ordering>
<after> <before>
<name>Fragmento3</name> <others />
</after> </before>
</ordering> </ordering>
</web-fragment> </web-fragment>
web-fragment.xml web.xml
<web-fragment> <web-app metadata-complete=”false”>
<name>Fragmento3</name> . . .
</web-fragment> </web-app>

Ejemplos de definicios de archivos web-fragment.xml y web.xml.

El orden de procesamiento será el siguiente: web.xml, Fragmento2, Fragmento3


y Fragmento1.

185
3: Desarrollo con Servlets y Java Server Pages

RESUMEN
A lo largo de esta unidad hemos dado las pautas fundamentales que hay que
tener en cuenta para manejarnos con servlets y Java Server Pages en la versión
6 de la plataforma Java Enterprise Edition. Además, se ha ilustrado su uso con
la implementación de ejemplos sencillos en NetBeans. En definitiva, al finalizar


esta unidad, debemos de ser capaces de lo siguiente:
Generar un servlet con NetBeans que procese la información llegada a través de los
métodos GET/POST de una petición HTTP.

■ Crear un servlet que mantiene información del número de accesos en gracias al uso
combinado de objetos tipo HttpSession y Cookie.

■ Cargar parámetros de configuración de un servlet y de una aplicación web a través de


los objetos ServletConfig y ServletContext.

■ Configurar el descriptor de despliegue web.xml de una aplicación web.

■ Utilizar anotaciones tanto en servlets como en JSP como alternativa al descriptor de


despliegue web.xml.

187

Das könnte Ihnen auch gefallen