3. Librerías de tags

 

3.1. Introducción a las librerías de tags


Las librerías de tags (taglibs) son conjuntos de etiquetas HTML personalizadas que permiten encapsular determinadas acciones, mediante un código Java subyacente. Es decir, se define lo que va a ejecutar la etiqueta mediante código Java, y luego se le da un nombre a la etiqueta para llamarla desde las páginas JSP, estableciendo la relación entre el nombre de la etiqueta y el código Java que la implementa. 

Por ejemplo, una página JSP que hace uso de librerías de tags podría tener este aspecto:

<%@ taglib uri="ejemplo" prefix="ej" %>
<html>
<body>
<h1>Ejemplo de librerias de tags</h1>
<ej:mitag>Hola a todos</ej:mitag>
<br>
<ej:otrotag/>
</body>
</html>

donde se utiliza una librería llamada ejemplo, que se simplifica con el prefijo ej, de forma que todos los tags de dicha librería se referencian con dicho prefijo y dos puntos, teniendo la forma ej:tag. Se utilizan así los tags mitag y otrotag.

Para poder utilizar las taglibs necesitamos tener una versión de JSP 1.1 o superior. Veremos a continuación aspectos generales sobre las librerías de tags, para pasar después a ver dos ejemplos concretos de librerías ya hechas. Más adelante veremos cómo crear nuestras propias librerías de tags. 

3.1.1. El gestor de tags

Cuando escribimos un tag (etiqueta) de una librería en una página JSP, el gestor de tags se pone en funcionamiento en el servidor para interactuar entre la página JSP y los objetos relacionados con dicho tag y su librería. 

Existen dos interfaces principales que describen un gestor de tags, en el paquete javax.servlet.jsp.tagext. Cada tag que se cree implementará una de las dos:

El gestor se encarga de llamar a su método doStartTag() cuando comienza el mismo. Este método puede devolver tres valores:

Cuando se termina el tag, se llama al método doEndTag() que puede devolver:

Estos valores devueltos permiten al contenedor JSP decidir cómo evaluar el resto de la página JSP.

Para los gestores de tipo BodyTag, se tienen los métodos doInitBody() y doAfterBody() para poder manipular el cuerpo del tag al procesarlo.

Los gestores de tags que se tengan deberán colocarse en el directorio WEB-INF/classes o WEB-INF/lib de la aplicación donde se utilicen (dependiendo de si son ficheros .class sueltos o están empaquetados en ficheros JAR).

3.1.2. El descriptor de la librería de tags

El descriptor de la librería de tags (TLD) es un fichero utilizado para interpretar páginas que incluyan dicha librería. Contiene directivas que describen la librería, para poderla utilizar. Es un fichero XML que mapea acciones con clases de tags.

1. Definición del fichero TLD en el descriptor de despliegue (web.xml)

Para encontrar y utilizar este fichero TLD, se utiliza una etiqueta de tipo taglib en el fichero descriptor de despliegue (web.xml) de nuestra aplicación. Así, para cada taglib que se emplee en la aplicación se tendrá un grupo de texto de este tipo en dicho fichero:

<taglib>
	<taglib-uri>identificador</taglib-uri>
	<taglib-location>fichero.tld</taglib-location>
</taglib>

2. Contenido del fichero TLD

Por otra parte, el fichero TLD de la librería tiene un contenido como:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, 
 Inc.//DTD JSP Tag Library 1.1//EN" 
 "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> 

<taglib> 

	<tlibversion>1.0</tlibversion> 
	<jspversion>1.1</jspversion>
	<shortname>pt</shortname>
	<uri>pruebatags</uri>
	<info>Librería de prueba</info> 

	<tag> 
		<name>prueba</name> 
		<tagclass>Prueba</tagclass>
		<bodycontent>empty</bodycontent>
		<info>Tag de prueba</info>
		<attribute> 
			<name>nombre</name>
			<required>false</required>
			<rtexprvalue>false</rtexprvalue>
		</attribute> 	
	</tag>
</taglib>

Se especifica al principio que es un fichero XML, y el DOCTYPE del mismo. La etiqueta raíz del documento es taglib, y puede tener como subetiquetas:

Tras las etiquetas anteriores, tendremos una etiqueta de tipo tag por cada tag de la librería. Esta etiqueta puede tener como subetiquetas:

3.1.3. Carga de taglibs en ficheros JSP

Para poder utilizar taglibs en ficheros JSP, se colocan al principio del fichero (antes de cualquier acción) directivas del tipo:

<%@ taglib uri="identificador" prefix="prefijo" %>

donde:

3.1.4. Ejemplo

Veremos ahora cómo utilizar una librería de tags. Supongamos que tenemos una librería llamada prueba, de forma que los ficheros Java que la implementan (los gestores de tags) están en un fichero prueba.jar, y el fichero descriptor es prueba.tld. Supongamos que el identificador (el uri) de la librería es prueba, y supongamos que la librería tiene un tag, llamado hola, sin cuerpo, que saca por pantalla el texto "hola a todos".

Para utilizar esta librería en una aplicación web, seguimos los pasos:

<taglib>
	<taglib-uri>prueba</taglib-uri>
	<taglib-location>
		/WEB-INF/prueba.tld
	</taglib-location>
</taglib>
<%@ taglib uri="prueba" prefix="pr" %>

donde el prefix puede ser el que queramos. Con esto, por ejemplo, podemos utilizar la librería así:

<%@ taglib uri="prueba" prefix="pr" %>
<html>
<body>
<pr:hola/>
</body>
</html>

Vemos que el prefijo se utiliza para anteponerlo al nombre de cada tag de la librería, en la forma prefijo:tag.

 

3.2. Ejemplo de librería: request

La librería request es una librería desarrollada en el proyecto Jakarta (los autores de los servidores Apache y Tomcat), y que permite acceder a la información acerca de una petición HTTP realizada. De esta forma podremos acceder a los parámetros de entrada de una petición GET o POST, a las cabeceras HTTP, cookies, etc.

Se tiene información detallada sobre esta librería en:

http://jakarta.apache.org/taglibs/doc/request-doc/intro.html

3.2.1. Uso de la librería

Para utilizar la librería request en una aplicación web, seguimos los pasos:

<taglib>
	<taglib-uri>
	http://jakarta.apache.org/taglibs/request-1.0
	</taglib-uri>
	<taglib-location>
	/WEB-INF/request.tld
	</taglib-location>
</taglib>
<%@ taglib 
uri="http://jakarta.apache.org/taglibs/request-1.0" 
prefix="req" %>

donde el prefijo puede ser el que queramos

3.2.2. Algunos tags de la librería

Veremos ahora algunos de los tags con los que cuenta esta librería. Para los ejemplos que se verán, suponemos que se ha indicado un prefijo (prefix) "req":

1. Información de la petición

request 

Para obtener información sobre la petición HTTP.

ATRIBUTOS

  • remoteUser: obtiene el login del usuario que realizó la petición
  • contentLength: obtiene la longitud en bytes de la petición
  • remoteHost: obtiene el nombre del cliente que realizó la petición, o la IP si no puede determinarse el nombre
  • etc...

EJEMPLO

<req:request id="req">
	Tamaño peticion: 
	<jsp:getProperty name="req" 
	 property="contentLength"/>
	<br>
	Direccion cliente: 
	<jsp:getProperty name="req" 
	 property="remoteHost"/>
</req:request>

2. Toma de parámetros

parameter

Obtiene el valor de un parámetro determinado. No tiene cuerpo.

ATRIBUTOS

EJEMPLO

<req:parameter name="param1"/>

parameters 

Recorre toda la lista de parámetros

ATRIBUTOS

  • como parámetro name se pasa el id asignado al tag
  • como parámetro property se pasa la propiedad que se quiere obtener, que pueden ser:
  • name: obtiene el nombre del parámetro
  • value: obtiene el valor del parámetro

EJEMPLO

<req:parameters id="id1">
	Nombre: 
	<jsp:getProperty name="id1" 
	 property="name"/>
	<br>
	Valor: 
	<jsp:getProperty name="id1" 
	 property="value"/>
	<br>
</req:parameters>
<req:parameters id="id1" name="param1">
	Valor: 
	<jsp:getProperty name="id1" 
	 property="value"/>
	<br>
</req:parameters>
parameterValues 

Recorre la lista de valores para un parámetro con múltiples valores. Debe estar incluido dentro de un tag parameters, recorriendo así los valores del parámetro que se esté explorando.

ATRIBUTOS

  • como parámetro name se pasa el id asignado al tag
  • como parámetro property se pasa value, que obtiene el valor del parámetro

EJEMPLO

<req parameters id="id1" name="param1">
	<req:parameterValues id="id2">
		Valor: 
		<jsp:getProperty name="id2" 
		 property="value"/>
		<br>
	</req:parameterValues>
</req:parameters>
equalsParameter

Comprueba si el valor del parámetro coincide con un determinado valor

ATRIBUTOS

EJEMPLO

<req:equalsParameter name="param1" 
 match="hola" value="false">
	El parametro no coincide
</req:equalsParameter>
<req:equalsParameter name="param1" 
 match="hola">
	El parametro si coincide
</req:equalsParameter>
existsParameter 

Comprueba si existe un determinado parámetro 

ATRIBUTOS

EJEMPLO

<req:existsParameter name="param1" 
 value="false">
	El parametro no existe
</req:existsParameter>

3. Cookies

cookie

Obtiene el valor de una cookie determinada. Similar a parameter.

<req:cookie name="nombre"/>
cookies

Recorre toda la lista de cookies

ATRIBUTOS

  • como parámetro name se pasa el id asignado al tag
  • como parámetro property se pasa la propiedad que se quiere obtener, que pueden ser, por ejemplo:
  • name: obtiene el nombre de la cookie
  • value: obtiene el valor de la cookie
  • maxAge: obtiene el tiempo de expiración

EJEMPLO

<req:cookies id="id1">
	Nombre: 
	<jsp:getProperty name="id1" 
	 property="name"/>
	<br>
	Valor: 
	<jsp:getProperty name="id1" 
	 property="value"/>
	<br>
	Max tiempo: 
	<jsp:getProperty name="id1" 
	 property="maxAge"/>
	<br>
</req:cookies>
equalsCookie

Obtiene si el valor de una cookie coincide con una cadena dada (similar a equalsParameter)

existsCookie

Obtiene si existe una cookie dada (similar a existsParameter)

4. Cabeceras

header

Obtiene el valor de una cabecera determinada (similar a cookie o a parameter)

<req:header name="nombre"/>
headerValues

Obtiene todos los valores de una cabecera con múltiples valores (similar a parameterValues)

headers

Recorre toda la lista de cabeceras. Similar a parameters.

equalsHeader

Obtiene si el valor de una cabecera coincide con una cadena dada (similar a equalsParameter)

existsHeader

Obtiene si existe una cabecera dada (similar a existsParameter)

3.2.3. Ejemplo de uso

Dado el siguiente formulario index.html:

<html>
<body>
	<form action="request.jsp">
		Nombre: 
		<input type="text" name="nombre">
		<br>
		Descripcion: 
		<input type="text" name="descripcion">
		<br>
		<input type="submit" value="Enviar">
	</form>
</body>
</html>

Al validarlo cargamos la página request.jsp, donde tenemos un ejemplo de cómo obtener los valores de los parámetros del formulario:

<%@ taglib 
uri="http://jakarta.apache.org/taglibs/request-1.0" 
prefix="req" %>

<html>
<body>
	Nombre: 
	<req:parameter name="nombre"/>
	<br>
	Descripcion: 
	<req:parameter name="descripcion"/>
	<br>
</body>
</html>

Aquí tenéis un fichero WAR con el ejemplo completo. Utiliza los ficheros TLD y JAR de la librería request, copiados ya en WEB-INF y WEB-INF/lib, respectivamente. Copiad el ejemplo en el directorio webapps de Tomcat, y probadlo con:

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

 

3.3. Ejemplo de librería: dbtags

La librería dbtags es otra librería desarrollada en el proyecto Jakarta que permite manipular bases de datos SQL. Requiere al menos la versión 1.2 de JSP (aunque en algunos servidores como Tomcat funciona con la 1.1). También necesita objetos DataSource, que no son parte de JDK estándar (SE). Para poderlos utilizar, tenemos que trabajar también con JDK Enterprise Edition, o bien utilizar la API para JDBC que corresponda.

Se tiene información detallada sobre esta librería en:

http://jakarta.apache.org/taglibs/doc/dbtags-doc/index.html

3.3.1. Uso de la librería

Para utilizar la librería dbtags en una aplicación web, seguimos los pasos:

<taglib>
	<taglib-uri>
	http://jakarta.apache.org/taglibs/dbtags
	</taglib-uri>
	<taglib-location>
	/WEB-INF/dbtags.tld
	</taglib-location>
</taglib>
<%@ taglib 
uri="http://jakarta.apache.org/taglibs/dbtags" 
prefix="sql" %>

donde el prefijo puede ser el que queramos

3.3.2. Algunos tags de la librería

Veremos ahora algunos de los tags con los que cuenta esta librería. Para los ejemplos que se verán, suponemos que se ha indicado un prefijo (prefix) "sql":

1. Conexión / Desconexión a la base de datos

connection

Este tag permite conectar a una base de datos, bien a través de una URL, o un objeto DataSource. Veremos el primer caso, por ser más común.

ATRIBUTOS

Luego, dentro, se tienen cuatro subtags:

EJEMPLO

<sql:connection id="con1">
	<sql:url>
	jdbc:mysql://localhost/prueba
	</sql:url>
	<sql:driver>
	org.gjt.mm.mysql.Driver
	</sql:driver>
	<sql:userId>root</sql:userId>
	<sql:password>mysql</sql:password>
</sql:connection>
closeConnection

Desconecta de una base de datos

ATRIBUTOS

EJEMPLO

<sql:closeConnection conn="con1"/>

2. Sentencias SQL

statement

Este tag permite crear una sentencia SQL para lanzarla a la base de datos.

ATRIBUTOS

Luego, dentro, se tienen los subtags:

EJEMPLO

<sql:statement id="s1" conn="con1">
	<sql:query>
	INSERT INTO datos(nombre, desc) 
	VALUES('nombre1','descripcion1')
	</sql:query>
	<sql:execute/>
</sql:statement>
<sql:statement id="s1" conn="con1">
	<sql:query>
		SELECT * FROM datos
	</sql:query>
	<sql:resultSet id="rs1">
		Nombre:
		<sql:getColumn colName="id"/>
		<br>
		Descripcion:
		<sql:getColumn position="2"/>
		<br>
	</sql:resultSet>
	<sql:wasEmpty>
		No hay resultados que mostrar
	</sql:wasEmpty>
	<sql:wasNotEmpty>
		Hay resultados que mostrar
	</sql:wasNotEmpty>
</sql:statement>

3.3.3. Ejemplo de uso

El siguiente ejemplo se conecta a esta base de datos MySQL para obtener todos los nombres y descripciones de su tabla datos:

<%@ taglib 
uri="http://jakarta.apache.org/taglibs/dbtags" 
prefix="sql" %>

<html>
<body>
	<sql:connection id="con1">
		<sql:url>
		jdbc:mysql://localhost/prueba
		</sql:url>
		<sql:driver>
		org.gjt.mm.mysql.Driver
		</sql:driver>
		<sql:userId>root</sql:userId>
		<sql:password>mysql</sql:password>
	</sql:connection>

	<sql:statement id="s1" conn="con1">
		<sql:query>
			SELECT * FROM datos
		</sql:query>
		<sql:resultSet id="rs1">
			Nombre:
			<sql:getColumn colName="nombre"/>
			<br>
			Descripcion:
			<sql:getColumn position="2"/>
			<br>
		</sql:resultSet>
		<sql:wasEmpty>
			No hay resultados que mostrar
		</sql:wasEmpty>
	</sql:statement>

	<sql:closeConnection conn="con1"/>
</body>
</html>

Aquí tenéis un fichero WAR con la aplicación. Además de los ficheros TLD y JAR de las dbtags (copiados ya en los directorios WEB-INF y WEB-INF/lib, respectivamente), también utiliza el fichero JAR para los drivers de conexión con MySQL (org.gjt.mm.mysql.Driver). Dicho fichero está ya incluido en el directorio WEB-INF/lib de la aplicación.

Para probar el ejemplo, seguid los pasos:

mysql -uroot -pmysql < prueba.sql
mysql -uroot -pmysql
GRANT ALL PRIVILEGES ON prueba.* to 
'root'@'localhost.localdomain' 
identified by 'mysql';

FLUSH PRIVILEGES;
http://localhost:8080/ejemplodbtags/dbtags.jsp

 

3.4. Otras consideraciones acerca de las librerías de tags

3.4.1. Uso de los tags

Se pueden colocar tags en varios lugares de nuestra página JSP. Podemos por ejemplo utilizar un tag request para obtener un valor de parámetro que utilizar en la sentencia SQL de un dbtag:

<sql:statement id="s1" conn="con1">
	<sql:query>
		SELECT * FROM datos WHERE 
		nombre = '<req:parameter name="nombre"/>'
	</sql:query>
	<sql:execute/>
</sql:statement>

O establecer un enlace en función de un parámetro:

<a href="http://<req:parameter name="url"/>">Enlace dinamico</a>

3.4.2. Comunicación entre JSP y las taglibs

En ocasiones nos puede interesar comunicar código JSP con código de taglibs: obtener dentro de JSP el valor de una taglib, o al revés, por ejemplo. 

Si queremos utilizar código JSP en una taglib, podemos hacerlo sin problemas. Por ejemplo, el siguiente código obtiene las 3 primeras columnas de cada registro de una SELECT:

<sql:statement id="s1" conn="con1">
	<sql:query>
		SELECT * FROM datos
	</sql:query>
	<sql:resultSet id="rs1">
		<% for (int i = 1; i <= 3; i++) { %>
		Valor:<sql:getColumn position="<%=i%>"/>
		<br>
		<% } %>
	</sql:resultSet>
</sql:statement>

El caso contrario, obtener valores de taglibs dentro de código JSP, es más complejo de tratar. Algunas etiquetas instancian código Java que es directamente accesible desde JSP, con el nombre que se les da en la etiqueta. Por ejemplo, para saber si una conexión está cerrada, podemos hacerlo con:

<sql:connection id="con1">
	<sql:url>jdbc:mysql://localhost/prueba</sql:url>
	<sql:driver>org.gjt.mm.mysql.Driver</sql:driver>
</sql:connection>
...
<% if (con1.getClosed()) { %>
	La conexion esta cerrada
<% } %>

En otros casos la comunicación no es tan directa, y hay que ver en la documentación del tag en cuestión cómo podemos acceder a su valor. Por ejemplo, para la etiqueta getColumn , podemos utilizar un atributo to para indicar un nombre de variable donde guardar su valor. Luego, desde JSP, utilizando el método getAttribute() del objeto pageContext podemos acceder a dicho valor. Por ejemplo:

<sql:getColumn colName="nombre" to="nombrePersona"/>
...
<% if (pageContext.getAttribute("nombrePersona").equals(
   "Pepe")) { %>
	Hola Pepe
<% } %>

3.4.3. Más información

Podemos encontrar información detallada sobre las librerías de tags del proyecto Jakarta en:

http://jakarta.apache.org/taglibs/index.html