P. 1
Jstl

Jstl

4.0

|Views: 4,950|Likes:
Published by api-3732355

More info:

Published by: api-3732355 on Oct 17, 2008
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

03/18/2014

pdf

text

original

JSTL

Alejandro Ramírez [mailto:jano@1x4x9.info]
Este documento se publica bajo la licencia "Creative Commons Attribution License". Para ver una copia de la licencia visita http://creativecommons.org/licenses/by/1.0/ o envía una carta a Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. 04 abril 2004 Revision 1 Revision 2 Revision History 04 abril 2004 alpha JSTL 1.0 25 mayo 2004 alpha JSTL 1.1

Tutorial y referencia de la especificación JavaServer Pages Standard Tag Library [http://www.jcp.org/en/jsr/detail?id=52] (JSTL) versión 1.1.

Table of Contents
Introducción ......................................................................................................... 1 Introducción ................................................................................................. 1 ¿Que es JSTL? ............................................................................................. 3 JSTL es fácil ................................................................................................ 4 Historia de JSTL ........................................................................................... 4 Instalar JSTL ................................................................................................ 4 Expression Language (EL) ...................................................................................... 8 EL .............................................................................................................. 8 Operadores .................................................................................................10 Literales .....................................................................................................11 Objetos implícitos ........................................................................................12 Funciones EL ..............................................................................................15 Etiquetas ............................................................................................................19 Core ..........................................................................................................19 Bases de datos .............................................................................................28 I18n y formateo ...........................................................................................34 XML .........................................................................................................44 Validadores de bibliotecas (TLVs) ..........................................................................50 ¿Que es un TLV? .........................................................................................50 TLVs de JSTL .............................................................................................51 Repaso a XPath ...................................................................................................52 ¿Que es XPath? ...........................................................................................52 Selección ....................................................................................................52 Expresiones XPath .......................................................................................55 Métodos .....................................................................................................55

Introducción
Introducción
JSP
¿Que es JSP?
1

JSTL

• • •

JSP significa Java Server Pages (Páginas Java en el Servidor). JSP es una tecnología Java para escribir programas que se ejecutan en el servidor. Existen muchos servidores capaces de ejecutar páginas JSP: Tomcat [http://jakarta.apache.org/tomcat/], JBoss, Resin, etc.

¿Que es una página JSP?

• • • • •

Una página JSP es un fichero de texto. Una página JSP es HTML convencional al que se le añaden instrucciones JSP ejecutables. Las instrucciones JSP están formadas por etiquetas similares a las del código HTML. Una página JSP tiene la extensión .jsp. Este es un ejemplo de página JSP: <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" <jsp:useBean id="now" class="java.util.Date" /> <html> <body> Hoy es <fmt:formatDate value="${now}" dateStyle="full" /> </body> </html> y su resultado %>

Figure 1.

¿Como se ejecuta?
• • • Si el usuario pide una página con extensión .html el servidor se la envía. Si el usuario pide una página con extensión .jsp el servidor ejecuta el JSP y añade el resultado al HTML original de la página. Para ejecutar una página JSP, el servidor realiza internamente varias operaciones: • • • Convierte la página JSP en código Java. Compila el código Java. Ejecuta el código Java.

¿Para que sirve?

• •

Programar con instrucciones JSP es más rápido porque no necesitamos compilar. JSP permite crear páginas dinámicas (o sea, páginas cuyo contenido varia en cada ejecución). 2

JSTL

• • •

Con JSP podemos responder a peticiones o información que el usuario nos envía. Con JSP podemos acceder a bases de datos o realizar cualquier operación posible con Java. JSP puede incluir instrucciones JSP y/o código en Java pero este último no es aconsejable porque produce páginas complicadas de mantener.

JSTL
¿Que es JSTL?
• • • • JSTL significa Java Standard Template Library (biblioteca de etiquetas estándar para Java). JSTL es un subconjunto de las etiquetas disponibles en JSP 2.0. JSTL no contiene código Java. JSTL es sencillo.

¿Qué requiere?
• • • Conocimientos básicos acerca del desarrollo de aplicaciones Web en Java. Un servidor capaz de ejecutar JSP 2.0. Instalar una implementación de JSTL: jstl-1.0.2.jar [http://www.ibiblio.org/maven/jstl/jars/jstl-1.0.2.jar] (20k), standard-1.0.4.jar [http://www.ibiblio.org/maven/taglibs/jars/standard-1.0.4.jar] (503k).

¿Que es JSTL?
JSTL es una biblioteca que implementa funciones de uso frecuente en aplicaciones JSP. En concreto, JSTL proporciona • Cinco bibliotecas de etiquetas JSP: • • • • • • • Funciones comunes de iteración sobre datos, operaciones condicionales, e importación de otras páginas. Internacionalización y formateo de texto. Funciones de manipulación de cadenas. Procesamiento de XML. Acceso a bases de datos.

Un lenguaje de expresión para referenciar objetos y sus propiedades sin necesidad de código Java. Validadores de bibliotecas de etiquetas (Tag Library Validators, TLVs).

JSTL requiere un contenedor de JSP 2.0. 3

JSTL

JSTL es fácil
Por su simplicidad, JSTL solo requiere conocimientos rudimentarios de Java, JSP, y aplicaciones Web. Cualquier desarrollador puede comenzar a usarlo de forma casi inmediata. JSTL facilita la referencia a objetos: <%-- con JSP --%> <%= session.getAttribute("username").getFirstName()%> <%-- con JSTL --%> ${sessionScope.username.firstName} [PENDIENTE] más ejemplos.

Historia de JSTL
Con JSTL se pretendía recopilar las etiquetas JSP más usadas en una biblioteca estándar que pudiera usarse en todos los contenedores JSP La especificación JSTL se desarrollo bajo el auspicio del JCP [http://www.jcp.org/en/home/index] (Java Community Process, Proceso Comunitario Java). El JCP es un proceso supervisado por SUN pero abierto a empresas, e individuos particulares, que guía el desarrollo y aprobación de los estándares para el lenguaje Java. En la actualidad (mayo 2004) el JCP cuenta con 700 participantes. Las iniciativas para crear un estándar dentro del proceso JCP se conocen como JSR (Java Specificacion Request, Petición de Especificación Java). La JSR nº 52 [http://www.jcp.org/jsr/detail/52.jsp] se llamó "A Standard Tag Library for JavaServer Pages", o abreviadamente JSTL. Fue solicitada originalmente por Eduardo Pelegri-Llopart y Anil Vijendran, empleados de SUN. En su desarrollo participaron individuos como Jason [http://today.java.net/cs/user/print/au/8?x-t=full.view]Hunter [http://www.javahispano.org/text.viewer.action?file=jason_hun_es], y representantes de varias organizaciones (ASF, Adobe, BEA, y otras). La especificación JSTL 1.0 fue terminada el 11 de julio de 2002. Unos días después apareció la primera implementación [http://jakarta.apache.org/taglibs/doc/standard-1.0-doc/intro.html ] creada por miembros del proyecto Taglibs [http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html] de la fundación Apache. La última versión de JSTL a día de hoy (mayo de 2004) es la 1.1, implementada por el proyecto Taglibs. JSTL es opcional en J2EE 1.4.

Instalar JSTL
Descargar el software
Para trabajar con JSTL necesitamos • • Un kit de desarrollo java como el Java Standard Edition (J2SE) [http://java.sun.com/j2se/index.jsp] de Sun. Un servidor que ejecute Servlets y JSP como Tomcat [http://jakarta.apache.org/tomcat/]. JSTL 1.0 necesita JSP 1.2 y Servlets 2.3 implementadas por Tomcat 4. JSTL 1.1 requiere JSP 2.0 y Servlets 2.4, implementadas por Tomcat 5. O dicho de otro modo, si vas a trabajar con la última versión de JSTL (la 1.1) usa Tomcat 5. Una implementación de JSTL como la proporcionada por el proyecto Taglibs de Apache [http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html]. La distribución (jakartataglibs-standard-1.1.0.zip [http://apache.rediris.es/jakarta/taglibs/standard/binaries/jakarta-taglibs-standard-1.1.0.zip]) contiene documentación, ejemplos, la implementación en sí, y varios jars de dependencias. Si qui4

JSTL

eres ahorrar tiempo baja solo los jars siguientes: jstl-1.0.2.jar [http://www.ibiblio.org/maven/jstl/jars/jstl-1.0.2.jar] (20k), standard-1.0.4.jar [http://www.ibiblio.org/maven/taglibs/jars/standard-1.0.4.jar] (503k). • Si vas a trabajar con expresiones XPath necesitaras jaxen-full.jar, y saxpath.jar, de la distribución de Jaxen [http://jaxen.org/], el motor XPath escogido por Sun para JSTL. Jaxen es un interfaz XPath para evaluar expresiones en DOM, JDOM, dom4j, o EXML. Esta presente en el Web Services Developer Pack de Sun.

El fichero jar jstl-1.0.2.jar contiene clases javax.servlet.jsp.jstl.* con la API de JSTL [http://java.sun.com/webservices/docs/1.0/api/index.html]. El fichero standard-1.0.4.jar contiene los paquetes [http://jakarta.apache.org/taglibs/doc/standard-doc/standard/index.html] con la implementación de JSTL.

Instalar Tomcat
Para instalar Tomcat • • Usamos un paquete especifico de nuestro sistema operativo, o simplemente bajamos la distribución en zip o tar.gz y la descomprimimos donde nos plazca. Establecemos la variable de entorno CATALINA_HOME apuntando al directorio de instalación.

Con la distribución en zip/tar.gz el resultado es similar a este:

Figure 2. Tomcat 5 en Windows
Cada directorio tiene un propósito, pero por ahora solo necesitamos saber que en bin están los scripts de arranque del servidor, y en webapps las aplicaciones Web.

Crear una aplicación de ejemplo
En Tomcat, cada aplicación Web se añade en un subdirectorio de CATALINA_HOME/webapps. Además el estándar requiere que tenga cierta estructura de directorios. Sin entrar en detalles, necesitaremos una estructura como esta: $CATALINA_HOME/webapps/miAplicacion ####WEB-INF ####classes ####lib commons-logging-1.0.3.jar jstl-1.0.2.jar standard-1.0.4.jar Observa que web.xml no es obligatorio según la especificación Servlet [http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html], y tampoco necesitamos crearlo para declarar los descriptores de etiquetas, porque desde JSP 1.2 es posible (y aconsejable) empaquetarlos con la propia implementación binaria. En JSTL los descriptores están en el fichero standard-1.0.1.jar. En cualquier caso, no esta de más añadir un web.xml. Se coloca bajo el directorio WEB-INF:

<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com version="2.4">

5

JSTL

<description>JSTL test</description> <display-name>JSTL test</display-name> </web-app> Si reiniciamos Tomcat, la aplicación será accesible en http://localhost:8080/miAplicacion [http://localhost:8080/myApp/], pero no veremos nada a menos que añadamos alguna página JSP.

Crear una página JSP con JSTL
Siguiendo con la aplicación Web de la sección anterior, vamos a crear una página JSTL. En toda página JSP hay que declarar la biblioteca a la que pertenece cada etiqueta que usemos. Puesto que son varias líneas, lo más comodo es hacer las declaraciones en un fichero aparte, y luego incluir dicho fichero en nuestras páginas JSP. Este sistema evita repetir el mismo texto en todas las páginas, y si en el futuro añadimos más bibliotecas, solo tendremos que modificar un único fichero.

Añade una página $CATALINA_HOME/webapps/miAplicacion/taglibs.jsp con las siguientes declaraciones: <%@ <%@ <%@ <%@ <%@ taglib taglib taglib taglib taglib prefix="c" prefix="fmt" prefix="x" prefix="sql" prefix="fn" uri="http://java.sun.com/jstl/core" %> uri="http://java.sun.com/jstl/fmt" %> uri="http://java.sun.com/jstl/xml" %> uri="http://java.sun.com/jstl/sql" %> uri="http://java.sun.com/jsp/jstl/functions" %>

Añade una página $CATALINA_HOME/webapps/miAplicacion/index.jsp que importe la anterior usando una directiva include: <%@include file="taglibs.jsp" %> <html> <body> <c:out value="Hola mundo"/> </body> </html> En este ejemplo hemos usado la etiqueta c:out de la librería core para mostrar un mensaje.

Generar un proyecto JSTL con Maven
En la sección anterior creamos un proyecto de ejemplo directamente sobre el servidor Tomcat. Vale como prueba, pero en proyectos complejos resulta más práctico crear la aplicación en un directorio aparte para no mezclar el entregable (proyecto terminado), con el código fuente original. Herramientas como Ant o Maven, nos permiten automatizar la construcción y despliegue de una aplicación a partir de su código fuente. Normalmente comenzamos un proyecto escribiendo un script, pero si somos usuarios de Maven podemos generar automáticamente una aplicación de ejemplo que tomaremos como punto de partida.

Warning
Maven es una herramienta similar a Ant pero más flexible y compleja. Si eres principiante probablemente te traiga más complicaciones que beneficios. Maven permite generar proyectos de ejemplo (script incluido) para varias tecnologías usando el plugin genapp [http://maven.apache.org/reference/plugins/genapp/goals.html]. Por ahora existen plantillas para JSTL, Struts, Struts+JSTL, EJB, y otros. A continuación se explica como. Genapp necesita XDoclet [http://xdoclet.sourceforge.net/], así que primero instalamos el plugin Maven-XDoclet. Maven descargará automaticamente las de Internet las dependencias necesarias. 6

JSTL

$ maven plugin:download -DartifactId=maven-xdoclet-plugin -DgroupId=xdoclet -Dve __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 Intentando descargar junit-3.8.1.jar. ................ . Intentando descargar servletapi-2.3.jar. ........... . Intentando descargar jstl-1.0.2.jar. .... . Intentando descargar standard-1.0.4.jar. ....................................................................... . Intentando descargar cactus-13-1.6dev-20040115.jar. ................................... . Intentando descargar commons-logging-1.0.3.jar. ...... . Intentando descargar xdoclet-1.2.jar. .................... . Intentando descargar xdoclet-web-module-1.2.jar. ...... Intentando descargar xdoclet-ejb-module-1.2.jar. ............................ . Intentando descargar xjavadoc-1.0.2.jar. .................................. . Intentando descargar httpunit-1.5.4.jar. ................................................. . Intentando descargar jtidy-4aug2000r7-dev.jar. .................... . Intentando descargar commons-jelly-tags-xml-20030211.142705.jar. .... . build:start:

plugin:download-artifact: [mkdir] Created dir: C:\.maven\repository\xdoclet\plugins [echo] repo is 'http://www.ibiblio.org/maven' [echo] trying to download http://www.ibibl....ins/maven-xdoclet-plugin-1.2.j ..... plugin:download: [delete] Deleting 1 files from D:\java\apache\maven\plugins [delete] Deleting 9 files from C:\.maven\plugins [delete] Deleted 2 directories from C:\.maven\plugins [copy] Copying 1 file to D:\java\apache\maven\plugins BUILD SUCCESSFUL Total time: 1 minutes 43 seconds $ Ya podemos generar nuestra aplicación de ejemplo. Nos situamos en un directorio cualquiera y hacemos esto: $ maven genapp __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \

~ intelligent projects ~ 7

JSTL

|_|

|_\__,_|\_/\___|_||_|

v. 1.0-rc2

Intentando descargar commons-jelly-tags-interaction-20030211.143817.jar. .. . Enter a project template to use: [default] web-jstl Please specify an id for your application: [app] Please specify a name for your application: [Example Application] [example.web]

Please specify the package for your application: build:start:

genapp: [copy] Copying 1 file to D:\desarrollo\myApp\src\java\example\web [copy] Copying 1 file to D:\desarrollo\myApp\src\test\example\web [copy] Copying 2 files to D:\desarrollo\myApp\src\test-cactus\example\web [copy] Copying 2 files to D:\desarrollo\myApp [copy] Copying 5 files to D:\desarrollo\myApp BUILD SUCCESSFUL Total time: 25 seconds Finished at: Sun Apr 25 18:52:22 CEST 2004 El proyecto resultante incluye las dependencias para usar Cactus, HttpUnit, y JUnit (de ahí que tarde tanto en descargarse).

Expression Language (EL)
EL
Antes de JSTL, JSP usaba Java para referenciar atributos dinámicos. Con JSTL ya no es necesario. Compara por ejemplo, la lectura de un parametro: <%-- con JSP --%> <%= request.getParameter("login") %> <%-- con JSTL --%> ${param.login} En JSTL se evita el uso de Java proporcionando un lenguaje de expresiones llamado EL (expression language). EL no es un lenguaje de programación en sí mismo, su único propósito es • • referenciar objetos y sus propiedades, y escribir expresiones simples.

EL se basa en las siguientes normas: • • Las expresiones JSTL comienzan con ${ y terminan con }. Lo que hay en medio es tratado como una expresión. Las expresiones se componen de • • Identificadores. Hay once identificadores reservados que corresponden a once objetos implícitos (los veremos luego). El resto de identificadores sirven para crear variables. Literales. Son números, cadenas delimitadas por comillas simples o dobles, y los valores 8

JSTL

true, false, y null. • • • • • Operadores. Permiten comparar y operar con identificadores y literales. Operadores de acceso. Se usan para referenciar propiedades de los objetos.

Podemos usar expresiones en cualquier parte del documento, o como valores de los atributos de etiquetas JSTL, exceptuando los atributos var y scope, que no aceptan expresiones. En cualquier sitio donde sea valido colocar una expresión, también será válido colocar más de una. Por ejemplo: value="Hola ${nombre} ${apellidos}". Las expresiones pueden contener operaciones aritméticas, comparaciones, operaciones booleanas, y agruparse mediante paréntesis. También pueden decidir cuando una variable existe o no (usando empty). Para acceder al campo de un bean java, o a un elemento de una colección (array, o Map), se usa el operador punto, o el operador corchete: ${bean.propiedad} ${map.elemento} ${header['User-Agent']} Si un campo de un bean es otro bean, podemos encadenar puntos para acceder a una propiedad del segundo bean: ${bean1.bean2.propiedad}

Las expresiones pueden aparecer como parte del valor de un atributo de una etiqueta: <c:out value="${2+2}"/> <c:out value="${nombre}"/> <c:if test="${tabla.indice % 2 == 0}">es par</c:if> O independientemente junto a texto estático como el HTML: <input type="text" name="usuario" value="${requestScope.usuario.nombre}"/>

EL es opcional en JSTL 1.0. Es por ello que cada una de las cuatro bibliotecas de JSTL tiene dos versiones: [PENDIENTE] • Versión EL: usa expresiones EL. Sus directivas taglib correspondientes son <%@ <%@ <%@ <%@ • taglib taglib taglib taglib prefix="c" prefix="fmt" prefix="x" prefix="sql" uri="http://java.sun.com/jstl/core_rt" uri="http://java.sun.com/jstl/fmt_rt" uri="http://java.sun.com/jstl/xml_rt" uri="http://java.sun.com/jstl/sql_rt" %> %> %> %>

Versión RT: usa expresiones del entorno de ejecución de JSP. Sus directivas taglib correspondientes son <%@ <%@ <%@ <%@ taglib taglib taglib taglib prefix="c_r" prefix="fmt_r" prefix="x_r" prefix="sql_r" uri="http://java.sun.com/jstl/core" uri="http://java.sun.com/jstl/fmt" uri="http://java.sun.com/jstl/xml" uri="http://java.sun.com/jstl/sql" %> %> %> %>

Si tenemos acceso a JSTL 1.1 es preferible la versión EL.

9

JSTL

Operadores
Los operadores y sus significados son los mismos que en otros lenguajes de programación.

Table 1. Resumen de operadores
Operador . [] () : ? +, -, *, / (o div), % (o mod) Descripción Acceso a propiedad o elemento de un Map. Acceso a elemento de un array o de un List. Agrupación de expresiones. Expresión condicional: condición ? valorSiCierto : valorSiFalso Suma, resta, multiplicación, división, resto.

== (o eq), != (o ne), < (o lt), > (o gt), <= (o Igualdad, desigualdad, menor que, mayor, menor le), >= (o ge) o igual que, mayor o igual que. && (o and), || (o or), ! (o not) empty función(argumentos) Operadores lógicos and, or, y not. Comprueba si una colección (array, Map, Collection) es null o vacía. Llamada a una función.

Table 2. Resumen de precedencia de operadores [PENDIENTE: función, empty, : ?]
[], . () - unario, not, !, empty *, /, div, %, mod +, - binario (), <, >, <=, >=, lt, gt, le, ge ==, !=, eq, ne && (o and) || (o or)

Acceso a datos
El operador punto (.) permite recuperar la propiedad de un objeto por su nombre. Ejemplo: ${libro.paginas} Las propiedades se recuperan usando las convenciones de los JavaBeans. Por ejemplo, en el código anterior, invocábamos el método libro.getPaginas() del objeto libro. El operador corchete ([]) permite recuperar una propiedad con nombre o indexada por número. Ejemplo: ${libro["paginas"]} ${libro[0]} ${header['User-Agent']} Dentro del corchete puede haber una cadena literal, una variable, o una expresión.

10

JSTL

Operadores aritméticos
Table 3.
Operador + * / div % mod suma resta multiplicación división resto Descripción

Operadores lógicos
Table 4.
Operador && and || or ! not Descripción true si ambos lados son ciertos true si alguno de los lados son ciertos true si la expresión es falsa

Operadores relacionales
Table 5.
Operador == eq != ne < lt > gt <= le >= ge Descripción comprobación de igualdad comprobación de desigualdad menor que mayor que menor o igual que mayor o igual que Ejemplo ${5 == 5} ${5 != 5} ${5 < 7} ${5 > 7} ${5 le 5} ${5 ge 6} Resultado true false true false true false

Operador empty
El operador empty comprueba si una colección o cadena es vacía o nula. Ejemplo: ${empty param.login} Otra manera de hacerlo es usando la palabra clave null: ${param.login == null}

Literales
En expresiones EL podemos usar números, caracteres, booleanos (palabras clave true, false), y nulls (palabra clave null).

11

JSTL

Objetos implícitos
Ciertos objetos son automáticamente accesibles a cualquier etiqueta JSP. A través de ellos es posible a cualquier variable de los ámbitos page, request, session, application, a parametros HTTP, cookies, valores de cabeceras, contexto de la página, y parámetros de inicialización del contexto. Todos, excepto pageContext, están implementados usando la clase java.util.Map.

Table 6. Objetos implicitos
Objetos implicitos pageScope requestScope sessionScope applicationScope param paramValues header headerValues cookie initParam pageContext contiene Variables de ámbito página. Variables de ámbito request. Variables de ámbito session. Variables de ámbito application. Parametros del request como cadenas. Parametros del request como array de cadenas. Cabeceras del request HTTP como cadenas. Cabeceras del request HTTP como array de cadenas. Valores de las cookies recibidas en el request. Parametros de inicialización de la aplicación Web. El objeto PageContext de la página actual.

Ejemplo: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <%-- ACCESO A TODOS LOS ELEMENTOS --%> <c:forEach items="${header}" var="item"> <c:out value="${item}"/><br/> </c:forEach> <br/> <%-- ACCESO POR NOMBRE CON PUNTO: objeto.propiedad --%> Host: <c:out value="${header.Host}"/> <br/> <%-- ACCESO POR NOMBRE CON CORCHETES: objeto['propiedad'] Usar este formato evita que se interprete el nombre como una expresión. Por ejemplo: queremos la propiedad "Accept-Language" no una resta entre las variables Accept y Language. --%> Host: <c:out value="${header['Host']}"/> <br/> Accept-Language: <c:out value="${header['Accept-Language']}"/> <br/> El resultado es

accept-encoding=gzip, deflate cache-control=no-cache connection=Keep-Alive referer=http://127.0.0.1:8080/sampleJSTL/ host=127.0.0.1:8080 accept-language=es user-agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; MyIE2; .NET CLR 1. cookie=JSESSIONID=E58368E8FFA066A654750C4CED08AA88 accept=*/* 12

JSTL

Host: 127.0.0.1:8080 Host: 127.0.0.1:8080 Accept-Language: es

pageContext
Aquí se listan algunos de los valores disponibles en el contexto de la página. Existen otros que podemos consultar en el javadoc. Por ejemplo, pageContext.request.authType esta ejecutando el método HttpServletRequest.getAuthType() [http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getAuthType()]. De igual modo podemos acceder al resto de métodos.

Table 7. pageContext
Expresión Descripción Ejemplo ${pageContext.excepti Devuelve una descripción del "Algo ha ido mal" on.message} error cuando la página en curso es una página de error JSP. ${pageContext.errorDa Información de un error JSP. ta} ${pageContext.request Tipo de autentificación usado .authType} en la página. BASIC

${pageContext.request Identificador del usuario fulano .remoteUser} (cuando esta en uso la autentificación del contenedor). ${pageContext.request Nombre (también llamado con- /apuntes-jstl .contextPath} texto) de la aplicación. ${pageContext.request Array de cookies. .cookies} ${pageContext.request Método HTTP usado para ac.method} ceder a la página. ${pageContext.request Query de la página (el texto de .queryString} la URL que viene despues del PATH) ${pageContext.request URL usada para acceder a la .requestURL} página. ${pageContext.session Contiene true si la sesión es .new} nueva, false si no lo es. ${pageContext.servlet Información sobre el conteneContext.serverInfo} dor JSP. GET p1=valor&p2=valor

http://localhost/app/pa gecontext.jsp true Tomcat 5.0.1

Pruebalo tu mismo, añade la página pageContext.jsp a tu aplicación con este contenido: <%@include file="taglibs.jsp" %> <html> <body> authType: <c:out value="${pageContext.request.authType}"/> remoteUser: <c:out value="${pageContext.request.remoteUser}"/> contextPath: <c:out value="${pageContext.request.contextPath}"/> cookies: <c:out value="${pageContext.request.cookies}"/> method: <c:out value="${pageContext.request.method}"/> queryString: <c:out value="${pageContext.request.queryString}"/> requestURL: <c:out value="${pageContext.request.requestURL}"/> session.new: <c:out value="${pageContext.session.new}"/> 13

<br/> <br/> <br/> <br/> <br/> <br/> <br/> <br/>

JSTL

serverInfo: message: </body> </html>

<c:out value="${pageContext.servletContext.serverInfo}"/> <c:out value="${pageContext.exception.message}"/>

<br/>

Cuando visites http://127.0.0.1:8080/myApp/pageContext.jsp aparecerá algo como authType: remoteUser: contextPath: /sampleJSTL cookies: [Ljavax.servlet.http.Cookie;@1add463 method: GET queryString: requestURL: http://127.0.0.1:8080/sampleJSTL/pageContext.jsp session.new: false serverInfo: Apache Tomcat/4.1.29 message: Vemos que varios valores aparecen en blanco: • • authType y remoteUser porque no estamos usando autentificación. queryString porque no hay parametros, prueba con pageContext.jsp?var1=valor1&var2=valor2 [http://127.0.0.1:8080/myApp/pageContext.jsp?var1=valor1&var2=valor2]. message porque no es una página de error, y por tanto no existe una excepción en el contexto de página.

pageContext.errorData
En JSP 2.0, cuando se produce un error la excepción ocurrida está disponible en el ámbito request con el nombre javax.servlet.error.exception. Ademas, se adjunta al contexto de la página, información adicional en forma de bean con nombre errorData. Este bean tiene las siguientes propiedades:

Table 8.
Propiedad requestURI servletName statusCode throwable String String int Throwable Tipo Java Descripción URI de la petición fallida. Nombre de la página o servlet que lanzó la excepción. Código HTTP del fallo. La excepción que produjo el fallo.

Para declarar una página de error JSP que responda a un código o excepción, podemos usar el web.xml: <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/error.jsp</location> </error-page> <error-page> <exception-code>500</exception-code> <location>/error.jsp</location> </error-page>

14

JSTL

o una declaración para una página concreta: <%@ page errorPage="/error2.jsp" contentType="text/html" %> Ejemplo de página de error: <%@ page isErrorPage="true" contentType="text/html" %> <pre> URI de la petición fallida: ${pageContext.errorData.requestURI} Quien lanzo el error: ${pageContext.errorData.servletName} Código del fallo: ${pageContext.errorData.statusCode} Excepción: ${pageContext.errorData.throwable} La misma excepción anterior: ${requestScope['javax.servlet.error.exception']} </pre> Para probarla podemos emplear esta otra página que lanza intencionadamente una excepción: <%@ page errorPage="error.jsp" contentType="text/html" %> <% if (true) throw new Exception("just do it!"); %> El resultado será este: URI de la petición fallida: /sampleJSTL/null.jsp Quien lanzo el error: jsp Código del fallo: 500 Excepción: java.lang.Exception: just do it! La misma excepción anterior: java.lang.Exception: just do it!

Funciones EL
Las funciones representan un modo de extender la funcionalidad del lenguaje de expresiones. Se usan dentro de cualquier expresión EL, ejemplo: Mi nombre de usuario tiene ${fn:length(username)} letras. En el descriptor de la biblioteca de funciones, se establece una correspondencia entre el nombre de la función y un método estático de una clase Java: [PENDIENTE: explicar mejor como definir funciones de usuario] <function> <description> Returns the number of items in a collection or the number of characters in a string. </description> <name>length</name> <function-class> org.apache.taglibs.standard.functions.Functions </function-class> <function-signature> int length(java.lang.Object) </function-signature> </function> En JSTL 1.1 existen 16 funciones de manipulación de cadenas: • • • Alternar una cadena entre mayúsculas/minúsculas: toLowerCase, toUpperCase. Obtener una subcadena: substring, substringAfter, substringBefore. Eliminar el espacio en blanco en ambos extremos de una cadena: trim. 15

JSTL

• • • • •

Reemplazar caracteres en una cadena: replace. Comprobar si una cadena contiene a otra: indexOf, startsWith, endsWith, contains, containsIgnoreCase. Convertir una cadena en array (split), o un array en cadena (join). Codificar los caracteres especiales del XML: escapeXml. Obtener la longitud de una cadena: length.

La función length también puede aplicarse a instancias de java.util.Collection, caso en el cual, devolverá el número de elementos de una colección. Todas las funciones EL interpretan las variables no definidas o definidas con valor igual a null, como cadenas vacías.

fn:contains
Devuelve true si una cadena contiene a otra, false en caso contrario. fn:contains(string, substring) # boolean Si la cadena a buscar es vacía, siempre existirá coincidencia. Ejemplo: <%-- Muestra un mensaje si la variable query contiene la cadena 'sex' --%> <c:if test="${fn:contains('sex', query)}"> Access control configuration prevents your request from being allowed. Offending word: sex </c:if>

fn:containsIgnoreCase
Devuelve true si una cadena contiene a otra sin distinguir entre minúsculas/mayúsculas, false en caso contrario. fn:containsIgnoreCase(string, substring) # boolean Si la cadena a buscar es vacía, siempre existirá coincidencia. Ejemplo: <%-- Muestra un mensaje si 'james stratchan' es subcadena de username sin distinguir entre mayúsculas o minúsculas. --%> <c:set var="username" value="James Stratchan"/> <c:if test="${fn:containsIgnoreCase('james stratchan', username)}"> Hi James Stratchan! </c:if>

fn:endsWith
Devuelve true si una cadena termina con el sufijo indicado, false en caso contrario. fn:endsWith(string, suffix) # boolean Si la cadena a buscar es vacía, siempre existirá coincidencia. Ejemplo: 16

JSTL

<c:set var="username" value="James Stratchan"/> <c:if test="${fn:endsWith(username, 'tratchan')}"> Hi James Stratchan! </c:if>

fn:escapeXml
Codifica los caracteres que podrían ser interpretados como parte de las etiquetas XML. fn:escapeXml(string) # String Es equivalente a c:out con atributo xmlEscape="true".

fn:indexOf
Devuelve el índice (empezando desde cero) dentro de una cadena donde comienza otra cadena especificada. fn:indexOf(string, substring) # int Si la cadena a buscar es vacía devuelve cero (comienzo de la cadena). Si la cadena a buscar no se encuentra devuelve -1.

fn:join
Convierte en cadena los elementos de un array. El separador se usa para separar los elementos en la cadena resultante. fn:join(array, separator) # String Si el array es nulo devuelve la cadena vacía.

fn:length
Devuelve el número de caracteres en una cadena, o de elementos en una colección. fn:length(input) # integer Devuelve cero para cadenas vacías.

fn:replace
Recorre una cadena (inputString) reemplazando todas las ocurrencias de una cadena (beforeSubstring) por otra (afterSubstring). fn:replace(inputString, beforeSubstring, afterSubstring) # String El texto reemplazado no es vuelto a procesar para realizar más reemplazos. Si afterSubstring es vacía se eliminan todas las ocurrencias de beforeSubstring.

fn:split
Divide una cadena en subcadenas, usando como separador cualquier carácter de otra cadena. Los caracteres de la segunda cadena no forman parte del resultado. fn:split(string, delimiters) # String[]

17

JSTL

No se realiza reemplazo alguno cuando: • • La cadena a dividir es vacía (se devuelve la cadena vacía). La cadena de delimitadores es vacía (se devuelve la cadena original).

fn:startsWith
Comprueba si una cadena comienza por otra. fn:startsWith(string, prefix) # boolean Devuelve true si la cadena a buscar es vacía.

fn:substring
Devuelve un subconjunto de una cadena. Los índices comienzan en cero. La cadena resultante comienza en beginIndex y llega hasta el caracter en endIndex-1 (incluido). La longitud de la cadena es endIndex-beginIndex. fn:substring(string, beginIndex, endIndex) # String

• • • •

Si beginIndex es menor que cero se ajusta su valor a cero. Si beginIndex es mayor que la longitud de la cadena se ajusta su valor a la longitud de la cadena. Si endIndex es menor que cero o mayor que la longitud de la cadena, se ajusta su valor a la longitud de la cadena. Si endIndex es menor que beginIndex se devuelve una cadena vacía.

fn:substringAfter
Devuelve la porción de una cadena que viene a continuación de cierta subcadena. La cadena devuelta comienza en el siguiente caracter tras la subcadena buscada. fn:substringAfter(string, substring) # String Si no se encuentra la subcadena o si esta es vacía se devuelve la cadena original.

fn:substringBefore
Devuelve la porción de una cadena que viene antes de cierta subcadena. La cadena devuelta va desde el primer carácter hasta el carácter anterior a la subcadena buscada. fn:substringBefore(string, substring) # String Si no se encuentra la subcadena o si esta es vacía se devuelve la cadena original.

fn:toLowerCase
Convierte todos los caracteres a minúsculas. fn:toLowerCase(string) # String 18

JSTL

fn:toUpperCase
Convierte todos los caracteres a mayúsculas. fn:toUpperCase(string) # String

fn:trim
Elimina el espacio en blanco en los extremos de una cadena. fn:trim(string) # String

Etiquetas
Core
Etiquetas para iteración sobre datos, operaciones condicionales, e importación de datos de otras páginas

c:out
Muestra el resultado de una expresión. Su funcionalidad es equivalente a la de <%= %>.

Table 9.
Atributo value default escapeXml Descripción información a mostrar información a mostrar por defecto true si debe convertir caracteres especiales a sus correspondientes entidades (por ejemplo, &gt; para <). Requerido sí no no Por defecto ninguno cuerpo true

Ejemplos: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:out value="Hola mundo"/> <c:out value="${variableInexistente}" default="la expresión fallo"/> <c:out value="${variableInexistente}"> la expresión fallo </c:out> Para evitar que un nombre sea confundido con una expresión lo ponemos entre comillas: <c:out value="${header['User-Agent']}" default="navegador no especificado"/> Hemos usado comillas simples en User-Agent para que no se confundan con las comillas dobles que delimitan el valor del atributo, también podríamos haber usado \"User-Agent\": Ejemplo de creación dinámica de un documento XSL: [PENDIENTE: demasiado complejo para es19

JSTL

tar aqui?] <c:import url="/xsl/main.xsl" var="main"/>

<c:set var="xsl"> <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" <c:out value="${main}" escapeXml="false"/> </xsl:stylesheet> </c:set>

c:set
Table 10.
Atributo value target Descripción Información a grabar. Nombre de la variable cuya propiedad será modificada Propiedad a modificar Nombre de la variable en la que guardar. no no Requerido Por defecto cuerpo ninguno

property var scope

no no

ninguna ninguno page

Ámbito de la variable no en la que grabar la información (page, request, session, o application)

Ejemplos: <%-- graba la variable cuatro=4 en el ámbito page --%> <c:set var="cuatro" value="${2 + 2}"/> <%-- equivalente al anterior pero con ámbito session --%> <c:set var="cuatro" scope="session"> 4 </c:set> <%-- equivalente al anterior --%> <c:set var="cuatro" scope="session"> <c:out value="4"/> </c:set> Si colocamos el valor en el cuerpo de la etiqueta, se suprimen los espacios del comienzo y final del cuerpo.

c:remove
Table 11.
Atributo var Descripción Nombre de la variable a sí quitar. 20 Requerido -Por defecto

JSTL

Atributo scope

Descripción Ámbito de la variable a no quitar.

Requerido

Por defecto todos los ámbitos

Cuando no se especifica ámbito, la etiqueta busca en todos los ámbitos por turno, yendo del más especifico al más general (page, request, session, application), hasta encontrar una variable con ese nombre. Si la variable no se encuentra, la etiqueta termina sin error.

c:if
Table 12.
Atributo test Descripción Condición a evaluar. Solo procesa el cuerpo si es true. sí Requerido -Por defecto

var

Nombre del atributo no con el que grabar el resultado booleano de la condición. Ámbito en el que expo- no ner el atributo anterior.

ninguno

scope

page

En el cuerpo es posible colocar otras etiquetas, incluyendo otras <c:if>. Es útil guardar el resultado de evaluar la condición para evitar repetir los cálculos. Ejemplos: <c:if test="${pageContext.request.remoteUser == 'hpetra'}">päivää Petra!</c:if> <%-- establece una variable a null, que es lo mismo que no haberla definido --%> <c:set var="nulo" value="${null}"/> <%-- devuelve la cadena vacia --%> <c:out value="${nulo}"/>

<%-- la condición es true en ambos casos --%> <c:if test="${nulo == null}">la cadena es nula o no definida</c:if> <c:if test="${nulo == variableNoDefinida}">la cadena es nula o no definida</c:if

c:choose, c:when, c:otherwise
No tiene atributos. Acepta como hijos uno o más <c:when>. <c:when> tiene un atributo:

Table 13.
Atributo test Descripción Condición a evaluar sí Requerido -Por defecto

<c:otherwise> no tiene atributos.

21

JSTL

Ejecuta el cuerpo de la primera etiqueta when cuya condición evalúe a true, o el cuerpo de la etiqueta otherwise (si existe). Ejemplos: <c:choose> <c:when test="${hour>=7 && hour<=12}"> morning </c:when> <c:when test="${hour>12 && hour<=17}"> afternoon </c:when> <c:when test="${hour>17 && hour<22}"> evening </c:when> <c:otherwise>night</c:otherwise> </c:choose>

c:forEach
Permite iterar sobre los elementos siguientes: • • • • Arrays de objetos o tipos primitivos. Instancias de java.util.Collection, java.util.Map, java.util.Iterator, java.util.Enumeration. Cadenas delimitadas por comas. Instancias de javax.servlet.jsp.jstl.sql.Result (resultantes de una consulta SLQ con JSTL).

Es posible anidar varias etiquetas c:forEach.

Table 14.
Atributo items begin end step var Descripción Colección sobre la que no iterar. Elemento con el que empezar (0=primero). Elemento con el que terminar (0=primero). Procesa solo cada step elementos. Nombre del atributo con el que exponer el elemento actual. Nombre de la variable con la que exponer el estado de la iteración. no no no no Requerido Por defecto ninguno 0 último 1 (todos) ninguno

varStatus

no

ninguno

La variable varStatus tiene propiedades que describen el estado de la iteración:

Table 15. Propiedades de la variable varStatus
Atributo begin current end número número número 22 Tipo Requerido El valor del atributo begin. El elemento actual. El valor del atributo end.

JSTL

Atributo index count first last step número número boolean boolean número

Tipo

Requerido Índice del elemento actual dentro de la colección. Número de iteración (empezando en 1). Indica si estamos en la primera iteración. Indica si estamos en la última iteración. El valor del atributo step.

Ejemplos: <c:forEach items="${informe.filas}" var="fila"> <c:out value="${fila}"/> </c:forEach> Si se omite el atributo items, se itera sobre números:

<c:forEach begin="1" end="24" step="1" var="hour" varStatus="status"> <c:out value="${hour}"/> <c:if test="${status.count == 19}">here comes your 19nth nervous breakdown!</c <br/> </c:forEach>

c:forTokens
Permite descomponer una cadena en tokens. Analizar una cadena se llama parsing. Las partes en las que se descompone una cadena se llaman tokens.

Table 16.
Atributo items delims var Descripción Cadena sobre la que it- sí erar Caracteres delimitadores Nombre del atributo con el que exponer el token actual sí no Requerido Por defecto ninguno ninguno ninguno

Los delimitadores que aparecen uno tras otro son tratados como si solo existiera uno. Ejemplos:

<ul> <c:forTokens items="Tinky Winki,Dipsy,Laa-Laa,Po" delims="," var="teletubbie"> <li><c:out value="${teletubbie}"/></li> </c:forTokens> </ul> La salida de lo anterior es

23

JSTL

<ul> <li>Tinky Winki</li> <li>Dipsy</li> <li>Laa-Laa</li> <li>Po</li> </ul> Esto devuelve Dipsy,Laa-Laa que son los tokens con índice 2, y 3: <c:forTokens items="Tinky Winki,Dipsy,Laa-Laa,Po" delims="," var="teletubbie" begin="2" end="4"> <c:out value="${teletubbie}"/> </c:forTokens> Esto muestra el classpath de TOMCAT para esta aplicación web: <c:forTokens items="${applicationScope['org.apache.catalina.jsp_classpath']}" delims=";" var="item"> <c:out value="${item}"/><br/> </c:forTokens>

c:import, c:param
c:import
c:import proporciona toda la funcionalidad de jsp:include y añade otras: • • Permite incluir páginas de otros servidores. Permite guardar el texto leído en una variable.

Table 17.
Atributo url Descripción URL para importar la sí página. Es válido cualquier protocolo soportado por java.net.URL. Es decir, al menos HTTP, HTTPS, FTP, file, y JAR. Barra (/) seguido del no nombre de la aplicación local Nombre del atributo con el que exponer el texto importado. no Requerido -Por defecto

context

contexto actual

var

muestra en página

scope charEncoding

Ámbito del atributo an- no terior. Juego de caracteres con no el que importar los datos. Nombre de una variable no con la que exponer el 24

page ISO-8859-1

varReader

ninguno

JSTL

Atributo

Descripción java.io.Reader con que se lee la URL.

Requerido

Por defecto

En HTML, la URL relativa /images/smiley.jpg lee un fichero de la raiz del servidor web, pero en JSTL, esa misma URL lee el fichero de la raíz de nuestra aplicación web. Si quisieramos que la URL fuera relativa a otra aplicación Web usariamos <c:import context="/otraApplicacion" url="/directorio/pagina.jsp"/> Cuando dos páginas están en la misma aplicación web, comparten el mismo ámbito request, session, y application. Si las páginas estan en diferente aplicación y son accedidas mediante c:import, ambas comparten el ámbito request.

c:param
c:import puede tener hijos c:param, que se usan para pasar parametros a la URL a recuperar. Los atributos de c:param son

Table 18.
Atributo name value Descripción nombre del parametro valor del parametro sí no Requerido -cuerpo Por defecto

Si quieres que un bean sea accesible en otra página, seria engorroso convertirlo en una cadena de texto, es mejor usar c:set para guardar esta información.

Ejemplos
Cuando queremos reutilizar un texto lo grabamos en una variable: <c:import url="http://creativecommons.org/licenses/by/1.0/ " var="licencia"/> <c:out value="${licencia}"/> Podemos hacer que los contenidos leídos sirvan de entrada a otra etiqueta colocando c:import en el cuerpo de dicha etiqueta (suponiendo que esta última lo admita): <string:lowerCase> <c:import url="pagina.jsp"/> </string:lowerCase> El siguiente c:import recupera la URL http://www.universalmusic.fi/tiktak/index.php?id=tuotanto: <c:import url="http://www.universalmusic.fi/tiktak/index.php"> <c:param name="id" value="tuotanto"/> </c:import> Página pagina1.jsp: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <html> <body> <c:import url="weather.jsp"> <c:param name="city" value="Madrid"/> 25

JSTL

</c:import> El tiempo meteorológico fue importado de la página weather.jsp. </body> </html> Página weather.jsp: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:import url="http://localhost:8080/weatherService.rest"> <c:param name="id" value="${param.city}"/> </c:import>

c:redirect
Ejecuta un forward. Es decir, se para la ejecución de la página actual (no se ejecuta nada de lo que este por debajo de esta instrucción) y el navegador es enviado a otra URL. Sus atributos son

Table 19.
Atributo url context Descripción URL a la que redirigir. sí Barra (/) seguido del nombre de una aplicación local. no Requerido -contexto actual Por defecto

Ejemplos: <c:redirect url="weatherPopUp.jsp"/> <c:param name="city" value="Madrid"/> </c:redirect> <c:redirect context="/myOtherApp" url="/somePage.jsp">

c:url
Sirve para mostrar una URL o para grabarla en una variable. Sus atributos son:

Table 20.
Atributo value context Descripción Base URL a mostrar o almacenar. Barra (/) seguido del nombre de una aplicación local. sí no Requerido -contexto actual Por defecto

var scope

Nombre del atributo en no el que exponer la URL. Ámbito del atributo an- no terior.

ningúno page

Admite parámetros mediante c:param igual que en c:import. 26

JSTL

Esta etiqueta es útil por dos motivos: • • Preserva la información de sesión codificada en la URL. Permite usar URLs relativas a la aplicación web, no a la raíz del servidor.

Ejemplos: <img src="<c:url value="/imagenes/smiley.gif"/>"/>

c:catch
Normalmente los errores en una página JSP interrumpen la ejecución de la página y se envían al contenedor, que a su vez muestra un mensaje de error. La etiqueta c:catch permite capturar y tratar los errores. La alternativa a c:catch es usar páginas de error con JSP convencional.

Table 21.
Atributo var Descripción Variable para exponer no información sobre el error. Requerido Por defecto ninguno

Si hay un error en alguna sentencia del cuerpo de la etiqueta se interrumpe la ejecución y se continua después del catch. Aquí intentamos parsear el número FDJ34rm4 pero obviamente se produce un error: <%@include file="taglibs.jsp" %> <c:catch var="error"> <fmt:parseNumber var="total" value="FDJ34rm4"/> <%-- nunca llega aquí --%> ... </c:catch> <c:if test="${not empty error}"> I'm sorry Dave, Im afraid I can't parse that. Error details: <c:out value="${error}"/> </c:if> Para que una página redirija a otra en caso de fallar su procesamiento basta con colocar esta directiva en ella: <%@ page errorPage="error.jsp" session="false" %> Luego tendremos que crear la página de error, que deberá comenzar con esta línea: <%@ page isErrorPage="true" %> Un ejemplo de página de error con JSTL: <%@ page isErrorPage="true" %> <%@include file="taglibs.jsp" %> </html> <head>Incidencia en el sistema</head> <body> 27

JSTL

El error fue..<br/> <c:out value="${pageContext.exception.message}"/> </body> </html>

Bases de datos
Warning
Una aplicación es más mantenible si separa las capas de presentación, lógica, y acceso a datos. Acceder a datos desde el JSP solo es recomendable para prototipos.

sql:DataSource
Table 22.
Atributo dataSource driver url user password var Descripción Base de datos a usar. no Nombre de la clase JD- no BC a usar como driver. URL de la base de datos. no Requerido Por defecto ningúno ningúno ningúno ningúno ningúno ningúno

Nombre del usuario de no la base de datos. Password del usuario de la base de datos. Nombre de la variable que representa la base de datos. Ámbito de la variable anterior. no no

scope

no

page

Si no usamos var o scope, el datasource declarado reemplaza al datasource por defecto. Esta etiqueta no implementa pooling de conexiones, pero con ella podremos referenciar un dataSource preexistente que sí lo implemente. Para usar el driver de un fabricante, obviamente necesitaremos colocar en el classpath dicho driver. Normalmente descargamos un archivo jar y lo colocamos en el WEB-INF/lib. Como ejemplo, aqui están el de mysql [http://dev.mysql.com/downloads/connector/j/3.0.html], oracle [http://otn.oracle.com/software/tech/java/sqlj_jdbc/index.html], y HSQL [http://hsqldb.sourceforge.net/]. Ejemplo: Establecer un dataSource por defecto: <sql:setDataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test" user="alicia" password="secreto"/> Ejemplos para otras bases de datos: // Orace con driver JDBC tipo 4 <sql:setDataSource driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@maquina:puerto:instancia" ... 28

JSTL

// MySQL <sql:setDataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://maquina:puerto/baseDeDatos" ... // HSQL <sql:setDataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:." ...

// Puente JDBC-ODBC de SUN con driver de SUN. No recomendado para producción. // Usa el formato jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-valu <sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver" url="jdbc:odbc:nombreDsn;UID=uid;PWD=password" ... Creamos un dataSource y lo guardamos en una variable: <sql:setDataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test" user="alicia" password="secreto" var="development1"/> Cambiamos el dataSource por defecto al grabado en la variable anterior [TODO: request es el ámbito por defecto?]: <sql:setDataSource dataSource="${development1}" scope="request" />

sql:query
Se usa para consultar la base de datos.

Table 23.
Atributo sql Descripción Consulta SQL a ejecutar. Proveedor de conexiones. Requerido no si ponemos el SQL en el cuerpo de la etiqueta no 0 (primero) Por defecto cuerpo

dataSource startRow

Primeras filas a ignorar no (ej: 10=ignora las diez primeras filas). Máximo número de filas. no

maxRows var scope

Variable con la que ex- sí poner el resultado. Ámbito de la anterior variable. no

ningúno page

Esta etiqueta no muestra datos, solo los graba en la variable indicada por var. El atributo maxRows indica el número por defecto de filas a recuperar. Podemos asignar un valor a este atributo para cambiar el límite de filas, o asignar -1 si no queremos límite. 29

JSTL

Las propiedades disponibles son: • • • • • columnName: Lista de nombres de columnas. Podemos acceder a ella con paréntesis cuadrados o iterando sobre ella. limitedByMaxRows: Booleano que indica si el resultado contenía más de las filas indicadas por maxRows. rows: Acceso a filas usando por nombre. rowsByIndex: Acceso a filas por índice. rowCount: Número de filas.

Ejemplo: <sql:query var="users"> SELECT * FROM USERS </sql:query> Forma equivalente a la anterior: <sql:query var="users" sql="SELECT * FROM USERS"/> Suponiendo que el SQL este en una variable: <sql:query var="users" sql="${sql}"/> Podemos usar otras etiquetas para proporcionar una consulta SQL en el cuerpo de la etiqueta. Supongamos que por algún motivo te interesa mantener todas las consultas en un fichero XML y quieres recuperar la consulta que devuelve todos los usuarios: <x:parse var="doc"> <query> <getAllUsers> SELECT * FROM users </getAllUsers> </query> <x:parse> <sql:query var="doc"> <x:out select="$doc/query/getAllUsers"/> </sql:query> Vamos a acceder por nombre a la primera columna y por índice a la segunda: <sql:query var="savvyUsers"> SELECT name, phone_extension FROM USERS WHERE CLUE > 0 </sql:query> <ul> <c:forEach items="${savvyUsers.rows}" var="row"> <li> <c:out value="${row.name}"/>, <c:out value="${row[1]}"/> </li> </c:forEach> </ul> Almacena un máximo de 10 resultados e indica si había más de 10 resultados:

30

JSTL

<sql:query var="users" maxRows="10"> SELECT * FROM USERS </sql:query> <c:if test="${users.limitedByMaxRows}"> El resultado contiene más filas de las mostradas. </c:if>

sql:update
Se usa para modificar la base de datos.

Table 24.
Atributo sql dataSource var Descripción consulta SQL a ejecutar no proveedor de conexiones no ningúno Requerido Por defecto cuerpo

variable para guardar el no número de filas actualizadas ámbito de la anterior variable no

scope

page

Varios ejemplos: <sql:update> INSERT INTO SET cita = autor = date = </sql:update> citas "es reinventar el tornillo, digo.. la rueda, bueno, y el tornillo "Luis" "2004-03-03";

<sql:update sql="DELETE FROM citas WHERE autor = 'Luis'"/> <sql:update var="n"> DELETE FROM citas WHERE autor = 'Luis' </sql:update> Hemos borrado <c:out value="${n}"/> filas.

sql:param
Se usa para pasar parámetros a las consultas ajustando la codificación de caracteres de forma segura.

Table 25.
Atributo value Descripción valor del parámetro no Requerido Por defecto cuerpo

La etiqueta sql:param sustituirá los caracteres ? de las sentencias SQL. Los caracteres ? únicamente pueden usarse para sustituir un valor (string, número, u otro) en un comando SQL. Ejemplo: <sql:update> 31

JSTL

INSERT INTO PEOPLE(NAME, AGE, WEIGHT) VALUES(?,?,?) <sql:param value="${userName}"/> <sql:param value="${userAge}"/> <sql:param> <x:out select="${userWeight}"/> </sql:param> </sql:update>

¿Porque es importante?
Al pasar parametros a una consulta es importante ajustar la codificación de caracteres de forma segura para evitar el problema de inyección de código SQL. Supongamos la típica página de login/password que traslada directamente el valor de los campos del formulario a la sentencia SQL: SELECT FROM users WHERE user='fulano' AND password='secreto'; ¿Pero que ocurre si en ponemos una comilla simple en el campo usuario? No he encontrado un ejemplo real en JSP para ilustrar este comportamiento, pero valga esta Web en ASP: Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server Driver][SQL Server] Comilla no cerrada antes de la cadena de caracteres '' AND Passwd =''. /login.asp, línea 30 La sentencia es incorrecta, y además el mensaje de error muestra datos sobre las interioridades de la aplicación. Si volvemos a probar introduciendo esta cadena en el campo usuario ' OR Passwd<>' El resultado de la query será SELECT FROM xxxxx WHERE xxxxx='' OR Passwd<>'' AND Passwd=''; Observa que he puesto xxxxx en los campos que no conozco, pero tampoco me importa porque con gracias al OR, estoy forzando a devolver el contenido completo de la tabla. Probablemente el programa lea el primer usuario de la lista devuelta y asuma que esa es nuestra identidad, lo que puede propiciar actos criminales, y multas por no proteger adecuadamente los datos de los usuarios del sistema.

sql:dateParam
Table 26.
Atributo value type Ejemplo: <sql:query> SELECT * FROM USERS 32 Descripción fecha a sustituir en el carácter ? sí Requerido -timestamp Por defecto

time, date, o timestamp no

JSTL

WHERE BIRTHDAY < ? <sql:dateParam value="${myBirthday}"/> </sql:query>

sql:transaction
Se usa para lanzar actualizaciones y consultas bajo una transacción. Para ello las sentencias sql:update y sql:query se colocan como cuerpo de esta etiqueta. Todas las sentencias en una transacción tienen éxito o fallan como unidad, es decir si alguno de ellos falla se realiza un rollback de todos, y la base de datos queda como antes de comenzar la transacción. En el cuerpo también podemos poner texto estático, o cualquier etiqueta JSP. Si ocurre algún error en alguna etiqueta del cuerpo, la transacción realiza un rollback.

Table 27.
Atributo dataSource isolation Descripción DataSource proveedor de conexiones. Nivel de aislamiento. no no Requerido Por defecto

El dataSource de esta etiqueta será usado por todas las etiquetas contenidas en el cuerpo, independientemente de que en ellas se especifique un dataSource diferente. Esto es así porque las transacciones están vinculadas por definición a una única conexión. Los niveles de aislamiento son los mismos que en JDBC:

Table 28.
nivel read_uncommitted -read_committed serializable evitado evitado repeatable_read evitado dirty read? nonrepeatable reads? --evitado evitado ---evitado phantom reads?

• • •

dirty read es una lectura de filas que aun no han sido confirmadas (commited) por otra transacción. nonrepeatable read ocurre cuando el mismo SELECT devuelve resultados diferentes dentro de una misma transacción. phantom read es como una nonrepeatable read, pero solo ocurre respecto a filas que han sido añadidas desde la primera lectura, no en filas que hayan sido modificadas.

El modo serializable ofrece la mayor protección pero a mayor protección, menor rendimiento. Ejemplo: <%-Adding New User Accounts to MySQL http://dev.mysql.com/doc/mysql/en/Adding_users.html --%> <sql:setDataSource driver="com.mysql.jdbc.Driver" 33

JSTL

url="jdbc:mysql://localhost:3306/test" user="alicia" password="secreto" var="testDatabase"/> <sql:transaction dataSource="${testDatabase}"> <sql:update> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost' IDENTIFIED BY 'some_pass' WITH GRANT OPTION; </sql:update> <sql:update> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%' IDENTIFIED BY 'some_pass' WITH GRANT OPTION; </sql:update> </sql:transaction>

I18n y formateo
La internacionalización (i18n) consiste en preparar una aplicación para que funcione en distintos idiomas (incluyendo formateo de fecha y moneda).

i18n
fmt:bundle
Permite cargar recursos de mensajes específicos solo para una zona de la página. Ver fmt:message.

Table 29.
Atributo basename prefix Descripción Nombre del recurso a usar. Cadena a usar como prefijo de cada clave. sí no Requerido Por defecto ninguno ninguno

Ejemplo: <fmt:bundle basename="ApplicationResources"> <fmt:message key="welcome.user"/> </fmt:bundle>

fmt:message
Acepta una clave y devuelve el resultado correspondiente a la clave en el fichero de recursos especificado.

Table 30.
Atributo key bundle var scope Descripción Clave. Recurso. Variable en la que guardar el resultado. Ámbito de la variable anterior. 34 no no no no ninguno page Requerido Por defecto cuerpo

JSTL

El recurso consiste en un fichero de texto accesible a través del classpath que contiene pares nombre=valor como los usados en la clase java.util.Properties. Por ejemplo: welcome.user = Hola ${0}! label.password = contraseña La cadena ${0} es un parametro que podemos pasar a la cadena leída para personalizar el mensaje. Para ello se usa la etiqueta fmt:param que veremos más adelante. Por ejemplo, suponiendo un objeto usuario con un campo nombre, podríamos obtener la cadena Hola Jano! (suponiendo que Jano es el valor del campo nombre) con el siguiente código: <fmt:message key="welcome.user"> <fmt:param value="${usuario.nombre}"/> </fmt:message> El nombre del recurso debe establecerse • • • con la etiqueta fmt:setBundle, etiqueta fmt:bundle, o añadiéndolo como parametro del web.xml con clave javax.servlet.jsp.jstl.fmt.localizationContext.

El nombre del fichero cargado por esta será nombre_XX.properties, donde XX es el locale activo. Es decir, si el nombre es ApplicationResources, y el locale activo es en, se intentará cargar el fichero ApplicationResources_en.properties del classpath, y si no se encuentra, se probará con el nombre por defecto ApplicationResources.properties. Ejemplo de uso estableciendo un fichero de recursos por defecto: <fmt:setBundle basename="ApplicationResources"/> <fmt:message key="label.password"/> Ejemplo de uso estableciendo temporalmente un fichero de recursos: <fmt:bundle basename="ApplicationResources"> <fmt:message key="label.password"/> </fmt:bundle> Ejemplo de uso estableciendo un fichero de recursos por defecto en el web.xml: <context-param> <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> <param-value>ApplicationResources</param-value> </context-param> <fmt:message key="label.password"/>

fmt:param
Algunos mensajes aceptan parámetros, de forma parecida a los PreparedStatement de SQL. Ver fmt:message.

Table 31.

35

JSTL

Atributo value

Descripción Parametro a añadir. no

Requerido

Por defecto cuerpo

Ejemplo: <fmt:message key="welcome.user"> <fmt:param value="${usuario.nombre}"/> </fmt:message>

fmt:setBundle
Permite cargar recursos de mensajes específicos. Ver fmt:message.

Table 32.
Atributo basename var scope Descripción Nombre del recurso a usar. sí Requerido Por defecto ninguno ninguno page

Variable en la que gra- no bar el recurso. Ámbito de la variable anterior. no

Ejemplo: <fmt:setBundle basename="ApplicationResources"/> <fmt:message key="welcome.user"/>

fmt:setLocale

Table 33.
Atributo value Descripción Nombre del locale, o instancia de sí Requerido Por defecto ninguno

36

JSTL

Atributo . variant scope

Descripción Variedad, ejemplo: WIN, o MAC. Ámbito de aplicación de esta etiqueta. no no

Requerido

Por defecto ninguno page

El valor del locale se compone del código del lenguaje según el ISO-639 [http://www.loc.gov/standards/iso639-2/englangn.html] y el código del país según el ISO-3166 [http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html] separados por un carácter de subrayado. Ejemplo: <fmt:setLocale value="es_ES" scope="session"/> Si no establecemos un locale con esta etiqueta, el valor por defecto es el enviado por la cabecera Accept-Language del navegador. Si tal cabecera no esta presente se toma el locale de la máquina virtual donde se ejecuta el contenedor JSP.

fmt:requestEncoding ??

Formateo
fmt:formatNumber
Funciona como c:out pero permitiendo más control sobre el formato. Su uso básico es <fmt:formatNumber value="${variable}"/> que hace lo mismo que c:out pero comprueba el idioma del navegador (lo lee a través de la cabecera Accept-Language) para mostrar correctamente la cantidad. Por ejemplo, este código muestra el idioma preferente del navegador y formatea un número: <c:out value="${header['Accept-Language']}"/> <fmt:formatNumber value="1234567.89"/> el resultado para un navegador español será es 1.234.567,89 mientras que para uno inglés será en 1,234,567.89

Table 34.
Atributo value type Descripción Valor numérico a form- no atear. Si mostrar números, no monedas, o porcentajes. Código de moneda ISO-2417 (ver bsi37 no Requerido Por defecto cuerpo number (puede ser number, currency, o percent) ningúno

currencyCode

JSTL

Atributo

Descripción global.com [http://www.bsi-global. com/iso4217currency]). Solo funciona en JDK1.4 o superior.

Requerido

Por defecto

currencySymbol groupingUsed

Símbolo de la moneda (por ejemplo $). Si agrupar o no los dígitos antes del punto decimal.

no no

ningúno true

maxIntegerDigits Máximo número de dígitos a mostrar. minIntegerDigits Mínimo número de dígitos a mostrar. maxFractionDigits minFractionDigits pattern Máximo número de dígitos fraccionarios a mostrar. Mínimo número de dígitos fraccionarios a mostrar.

no no no

ningúno ningúno ningúno

no

ningúno

Patrón con el formateo no del número. Sigue la convención de java.util.Decima lFormat. Variable en la que gra- no bar el resultado. Ámbito de la anterior variable. no

ningúno

var scope

ningúno page

En JDK 1.4, el atributo currencyCode tiene preferencia sobre el atributo currencySymbol. En versiones anteriores ocurre al contrario. Ejemplos para tipos de valores <fmt:formatNumber value="1234567.89" type="number"/> 1,234,567.89 <fmt:formatNumber value="1234567.89" type="currency"/> $1,234,567.89 <fmt:formatNumber value="1234567.89" type="percent"/> 123,456,789% Ejemplos para valores de tipo moneda: <fmt:formatNumber value="1234567.89" type="currency"/> $123,456,789 <fmt:setLocale value="es"/> <fmt:formatNumber value="1234567.89" type="currency"/> ¤123,456,789 <fmt:formatNumber value="1234567.89" type="currency" currencySymbol="€"/> €1,234,567.89 <fmt:formatNumber value="1234567.89" type="currency" currencyCode="EUR"/> EUR1,234,567.89 38

JSTL

<fmt:formatNumber value="1234567.89" type="currency" currencyCode="EUR" currency EUR1,234,567.89 Ejemplos para agrupación y número de dígitos: <fmt:formatNumber value="1234567.89" groupingUsed="true"/> 1,234,567.89 <fmt:formatNumber value="1234567.89" groupingUsed="no"/> 1234567.89 Ejemplos para número de dígitos: <fmt:formatNumber value="1234567.89" maxIntegerDigits="5"/> 34,567.89 <fmt:formatNumber value="1234567.89" minIntegerDigits="10"/> 0,001,234,567.89 <fmt:formatNumber value="1234567.89" maxFractionDigits="1"/> 1,234,567.9 <fmt:formatNumber value="1234567.89" minFractionDigits="5"/> 1,234,567.89000 Ejemplo de patrón: 1.2345679E6 <fmt:formatNumber value="1234567.89" pattern="##0.#####E0"/> El formato de los patrones es el mismo que el empleado en la clase DecimalFormat [http://java.sun.com/j2se/1.4.2/docs/api/java/text/DecimalFormat.html].

fmt:formatDate
No acepta valores en el cuerpo. Requiere un atributo value con una variable que represente una fecha (conviene usar fmt:parseDate). Un modo rápido de crear una variable con una fecha es instanciar java.util.Date como bean: <jsp:useBean id="ahora" class="java.util.Date"/> <fmt:formatDate value="${ahora}"/>

Table 35.
Atributo value type dateStyle Descripción Fecha a mostrar. sí Si mostrar fechas, horas no o ambos. Estilo preferido para la no fecha. Estilo preferido para el no tiempo. Zona horaria usada para no formatear la fecha. Requerido Por defecto ningúno date (puede ser date, time, o both) default (puede ser default, short, medium, long) default (puede ser default, short, medium, long) Posibles valores [http://www.timeanddat e.com/library/abbreviati ons/timezones/]

timeStyle

timeZone

39

JSTL

Atributo pattern

Descripción Patrón de formateo. no

Requerido

Por defecto Ninguno. Ver SimpleDateFormat [http://java.sun.com/j2s e/ 1.4.2/docs/api/java/text/ SimpleDateFormat.html]. ningúno page

var scope

Variable en la que gra- no bar el resultado. Ámbito en el que gra- no bar la variable anterior.

El atributo timeZone permite especificar la zona horaria de una fecha. Puede tomar como valor cualquier abreviatura de las zonas horarias [http://www.timeanddate.com/library/abbreviations/timezones/]. Ejemplos para tipo de fecha: <jsp:useBean id="now" class="java.util.Date"/> Sep 5, 2004 <fmt:formatDate value="${now}" type="date"/> 5:00:30 PM <fmt:formatDate value="${now}" type="time"/> Sep 5, 2004 5:00:30 PM <fmt:formatDate value="${now}" type="both"/> Ejemplos para estilo de fecha: <jsp:useBean id="now" class="java.util.Date"/> Sep 5, 2004 <fmt:formatDate value="${now}" type="date" dateStyle="default"/> 9/5/04 <fmt:formatDate value="${now}" type="date" dateStyle="short"/> Sep 5, 2004 <fmt:formatDate value="${now}" type="date" dateStyle="medium"/> September 5, 2004 <fmt:formatDate value="${now}" type="date" dateStyle="long"/> Ejemplos para estilo de hora: 5:25:33 PM <fmt:formatDate value="${now}" type="time" timeStyle="default"/> 5:25 PM <fmt:formatDate value="${now}" type="time" timeStyle="short"/> 5:25:33 PM <fmt:formatDate value="${now}" type="time" timeStyle="medium"/> 5:25:33 PM CEST <fmt:formatDate value="${now}" type="time" timeStyle="long"/> El atributo pattern sigue la convención fijada para la clase SimpleDateFormat [http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html]: 40

JSTL

Table 36.
Caracter yy yyyy M MM MMM MMMM d dd EE EEEE H HH h hh m mm s ss S a zz zzzz Z 'cadena' Ejemplos de patrones: Descripción Año corto. Año completo. Número del més. Nombre corto del més. Nombre del més. Día del mes. Día del més con dos dígitos. Nombre corto del día. Nombre del día. Hora en formato militar. 02 2002 4 Apr April 5 05 Fri Friday 21 Ejemplo

Número de més con dos dígitos. 04

Hora en formato militar con dos 21 dígitos. Hora (1-12). Hora (1-12) con dos dígitos. Minuto. Minuto con dos dígitos. Segundo. Segundo con dos dígitos. Milisegundo. AM / PM Nombre corto de zona horaria. Zona horaria. Descripción de zona horaria. Cadena a incluir. 9 09 4 04 6 06 249 PM EST Eastern Standard Time -0500 'cadena'

Table 37.
Patrón yyyy.MM.dd G 'at' HH:mm:ss z EEE, MMM d, ''yy h:mm a hh 'o''clock' a, zzzz K:mm a, z yyyyy.MMMMM.dd GGG hh:mm aaa EEE, d MMM yyyy HH:mm:ss Z yyMMddHHmmssZ Resultado 2004.09.05 AD at 18:06:56 CEST Sun, Sep 5, '04 6:06 PM 06 o'clock PM, Central European Summer Time 6:06 PM, CEST 02004.September.05 AD 06:06 PM Sun, 5 Sep 2004 18:06:56 +0200 040905180656+0200

fmt:parseNumber
41

JSTL

Interpreta cadenas como números. Es necesario para pasar valores numéricos a algunas etiquetas como sql:param, fmt:formatNumber, y otras.

Table 38.
Atributo value type Descripción Cadena a interpretar como número. Como interpretarlo. no no Requerido Por defecto cuerpo number (puede ser number, currency, o percent) false ningúno. Ver SimpleDateFormat [http://java.sun.com/j2s e/ 1.4.2/docs/api/java/text/ SimpleDateFormat.html]. ningúno page

integerOnly pattern

Si descartar decimales. no Patrón de formato. no

parseLocale var scope

Locale a usar.

no

Variable en la que gra- no bar el resultado. Ámbito de la variable anterior. no

Ejemplo: java.util.Date.getTime() devuelve el número de milisegundos transcurridos desde 1 enero 1970 00:00:00 GMT, que son ahora: <jsp:useBean id="date" class="java.util.Date" /> <fmt:formatNumber value="${date.time}" />

fmt:parseDate
Interpreta cadenas como fechas. Usa el locale del contenedor JSP.

Table 39.
Atributo value type dateStyle Descripción Fecha a mostrar. no Si mostrar fechas, horas no o ambos. Estilo preferido para la no fecha. Estilo preferido para el no tiempo. Zona horaria usada para no formatear la fecha. Requerido date default (puede ser default, short, medium, long) default (puede ser default, short, medium, long) Ningúno. Posibles valores [http://www.timeanddat e.com/library/abbreviati ons/timezones/]. Ningúno. Ver SimpleDPor defecto cuerpo

timeStyle

timeZone

pattern

Patrón de formateo. 42

no

JSTL

Atributo

Descripción

Requerido

Por defecto ateFormat [http://java.sun.com/j2s e/ 1.4.2/docs/api/java/text/ SimpleDateFormat.html].

parseLocale var scope

Locale a usar.

no ningúno page

Variable en la que gra- no bar el resultado. Ámbito en el que gra- no bar la variable anterior.

Ver los identificadores de zonas horarias en http://java.sun.com/j2se/1.4/docs/api/java/util/TimeZone.html.

fmt:setTimeZone
Permite cambiar la zona horaria:

Table 40.
Atributo value Descripción Identificador de la zona sí horaria, o instancia de java.util.TimeZo ne. Variable en la que no guardar la zona horaria. Ámbito de la variable. no Requerido Por defecto Ninguno. Posibles valores [http://www.timeanddat e.com/library/abbreviati ons/timezones/]. ningúno page

var scope

Los posible valores del atributo value son los correspondientes al método estático java.util.TimeZone.getAvailableIDs(). Ejemplo: <fmt:setTimeZone value="GMT"/>

fmt:timeZone
Permite cambiar temporalmente la zona horaria. Se usa colocando en el cuerpo de la etiqueta, las instrucciones que queremos que se ejecuten en la nueva zona horaria.

Table 41.
Atributo value Descripción Identificador de la zona sí horaria. Requerido Por defecto Ningúno. Posibles valores [http://www.timeanddat e.com/library/abbreviati ons/timezones/].

Ejemplo: 43

JSTL

<fmt:timeZone value="GMT"> <jsp:useBean id="ahora" class="java.util.Date"/> <fmt:formatDate value="${ahora}"/> </fmt:timeZone>

XML
XPath en JSTL
La librería XML de JSTL usa XPath para obtener partes de los documentos XML con que opera. Si no conoces XPath, hay un pequeño tutorial en la última sección de este documento. En JSTL, cuando una expresión XPath devuelve algún nodo, se considera true, si no, false. Una variable XPath tiene el formato $nombre, o el formato $nombre1:nombre2. Por ejemplo: $sessionScope:usuario. En JSTL podemos usar los siguientes espacios de nombres para las variables:

Table 42.
Prefijo pageScope requestScope sessionScope applicationScope param header initParam cookie Significado variables de ámbito página variables de ámbito request variables de ámbito session variables de ámbito application parametros del request como cadenas cabeceras del request http como cadenas parametros de inicialización del contexto valores de las cookies

x:parse
Antes de poder usar un fichero XML debemos interpretarlo, o dicho en spanglish, parsearlo. Parsear es el proceso de analizar la sintaxis de la información y convertirla a un formato más manejable. Para parsear un documento xml en JSTL se usa x:parse.

Table 43.
Atributo xml Descripción Texto XML a parsear. Debe ser una cadena o una instancia de java.io.Reader. no Requerido Por defecto cuerpo

var

Nombre de la variable no con la que exponer el documento. El objeto resultante cumple el interfaz org.w3c.dom.Docu ment. Ámbito con el que ex- no poner la variable anteri44

ningúno

scope

page

JSTL

Atributo or. systemId

Descripción URI del documento ori- no ginal con la que resolver las entidades. Instancia de no org.xml.sax.XMLF ilter para filtrar el documento. Nombre de la variable con la que exponer el documento DOM. no

Requerido

Por defecto ningúno

filter

ningúno

varDom

ningúno

scopeDom

Ámbito con el que ex- no poner la variable anterior.

ningúno

Si usamos el atributo xml, el cuerpo de la etiqueta debe estar vacío. Normalmente importaremos el XML: <c:import var="noticias" url="http://www.javahispano.org/noticias.rdf"/> <x:parse xml="${noticias}" var="noticiasRDF"/> Este es un método equivalente a lo anterior: <x:parse var="noticiasRDF"> <c:import url="http://www.javahispano.org/noticias.rdf"/> </x:parse> Tras ejecutar el c:import anterior aparece un documento XML en el cuerpo. Tambien podemos escribirlo explicitamente: <x:parse var="transmision"> <correo> <de>hal9000@discovery.gov</de> <mensaje>All these worlds are yours except europa.</mensaje> </correo> <x:parse> Para referirnos al elemento mensaje del XML anterior usariamos $transmision/correo/mensaje. En general, podemos usar cualquier variable conteniendo un documento XML seguida de cualquier expresión XPath.

x:out
Evalúa y muestra el resultado de una expresión XPath.

Table 44.
Atributo select escapeXml Descripción Expresión XPath. Muestra ciertos caracteres como entidades. sí no Requerido -true Por defecto

Ejemplo: 45

JSTL

<x:parse var="mailfeed"> <mail> <received> <from>mta04ps.bigpond.com</from> <by>smtp01-01.mesa1.secureserver.net</by> </received> <received> <from>lerc-daemon.mta04ps.email.bigpond.com</from> <by>mta04ps.email.bigpond.com</by> </received> <subject>[SPAM] CONGRATULATION LUCKY WINNER</subject> </mail> </x:mail> Para mostrar el contenido del elemento subject usamos: <x:out select="$mailfeed/mail/subject"/>

x:set
Guarda el resultado de una expresión XPath en una variable.

Table 45.
Atributo select var Descripción Expresión XPath. sí Variable en la que no guardar el resultado de la expresión XPath. Ámbito en el que expo- no ner la variable anterior. Requerido -ningúno Por defecto

scope

page

Ejemplo: <x:parse var="DecentralizingREST"> <dissertation> <title> Extending the REpresentational State Transfer (REST) Architectural Style for Decentralized Systems </title> <author> <first>Rohit</first> <last>Kare</last> </author> </dissertation> </x:parse> <x:set var="autor" select="$DecentralizingREST/dissertation/author"/> La variable autor contiene el siguiente subconjunto del documento anterior: <author><first>Rohit</first><last>Kare</last></author>.

x:if
Table 46.

46

JSTL

Atributo select

Descripción Expresión XPath a sí evaluar. El cuerpo solo se procesa si resulta true. Variable en la que guardar el resultado booleano de la expresión XPath. no

Requerido --

Por defecto

var

ningúno

scope

Ámbito en el que expo- no ner la variable anterior.

page

Hay motivos por los que es útil guardar la expresión en una variable: • • Para no perder tiempo reevaluando la condición. Cuando la condición va a cambiar y queremos conservar el resultado.

Ejemplo: <x:parse var="RESTpapers"> <paper> <dissertation> <title> Extending the REpresentational State Transfer (REST) Architectural Style for Decentralized Systems </title> <author> <first>Rohit</first> <last>Kare</last> </author> </dissertation> </paper> </x:parse> <x:if select="$RESTpapers/paper//author/last[text()='Kare'"> At least one paper from Rohit Kare. </x:if>

x:choose, x:when, x:otherwise
Funcionan de modo similar a sus equivalentes de la librería core. <c:when> tiene un atributo:

Table 47.
Atributo select Descripción Expresión XPath a evaluar. Si es true procesa el cuerpo. sí Requerido Por defecto ninguno

En el ejemplo que vimos en la etiqueta anterior, usariamos este código para mostrar un mensaje según el autor de cada documento: <x:choose> <x:when select="$RESTpapers/paper//author/last[text()='Kare'"> 47

JSTL

Rohit Kare is a random guy from Caltech </x:when> <x:when select="$RESTpapers/paper//author/last[text()='Stratchan'"> James Stratchan is a folk working on 20+ open source projects. wow. </x:when> <x:otherwise> Unknown </x:otherwise> </x:choose>

x:forEach
Se usa para iterar sobre los elementos XML resultantes de ejecutar una expresión XPath.

Table 48.
Atributo select Descripción Expresión XPath sobre sí cuyos resultados vamos a iterar. Nombre de la variable con la que exponer el nodo actual. no Requerido Por defecto ningúno

var

ningúno

En cada iteración, el elemento correspondiente sirve de contexto respecto al que hacen referencia todas las expresiones del cuerpo. Si se anidan las etiquetas x:forEach, las etiquetas internas haran referencia al contexto de la iteración de la etiqueta externa. Volviendo al ejemplo de secciones anteriores: <x:parse var="RESTpapers"> <paper> <dissertation> <title> Extending the REpresentational State Transfer (REST) Architectural Style for Decentralized Systems </title> <author> <first>Rohit</first> <last>Kare</last> </author> </dissertation> </paper> </x:parse> Mostremos el título de cada documento: <x:forEach select="$RESTpapers//title"> <p><x:out select="."/></p> </x:forEach> En el atributo select de las etiquetas foreach y out podemos usar cualquier expresión XPath. Ahora un ejemplo que lee muestra una lista con las últimas noticias [http://www.javahispano.org/noticias.rdf] de javaHispano [http://www.javahispano.org]: <c:import var="noticias" url="http://www.javahispano.org/noticias.rdf"/> <x:parse var="doc" xml="${noticias}"/> <ul> <x:forEach select="$doc//*[name()='item']"> 48

JSTL

<li> <a href="<x:out select="./*[name()='link']"/>"> <x:out select="./*[name()='title']" /> </a> </li> </x:forEach> </ul>

x:transform
La etiqueta x:trasform sirve para aplicar XSLT al XML.

Table 49.
Atributo result scope Descripción ?? [PENDIENTE] ?? Ámbito con el que ex- no poner la variable anterior. Nombre de la variable no con la que exponer el documento resultante. El objeto resultante cumple el interfaz org.w3c.dom.Docu ment. Documento XML a transformar. Debe ser una cadena o una instancia de java.io.Reader. Hoja de estilo XSLT a aplicar. no Requerido ?? page Por defecto

var

ninguno

xml

cuerpo

xslt

--

Si colocamos un objeto javax.xml.transform.Result en el atributo result, y no especificamos var ni scope, el resultado de la transformación se guardará en un objeto del tipo mencionado. Ejemplo: <c:import var="xml" url="${urlXML}"/> <c:import var="xsl" url="${urlXSL}"/> <x:transform xml="${xml}" xslt="${xsl}"/> Puedes encadenar transformaciones, por ejemplo, docbook --> javahispano --> XHTML --> XHTML + CSS : <x:transform var="javahispano" xml="${docbook}" <x:transform var="xhtml" xml="${javahispano}" <x:transform var="styledXHTML" xml="${xhtml}" Si anidamos las etiquetas no es necesario usar variables temporales: <x:transform xslt="${summerStyle}"> <x:transform xslt="${jh2xhtml}"> <x:transform xslt="${docbook2jh}" xml="${docbook}"/> </x:transform> 49 xslt="${docbook2jh}"/> xslt="${jh2xhtml}"/> xslt="${summerStyle}"/>

JSTL

</x:transform> Podemos definir el xml y xsl dentro de la misma página: [PENDIENTE: copiar transformación del informe] <c:set var="xml"> ...[PENDIENTE] </c:set>

<c:set var="xsl"> <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" ...[PENDIENTE] </xsl:stylesheet> </c:set> <x:transform xml="${xml}" xslt="${xsl}"/>

x:param
Permite declarar parametros para su uso en hojas de estilo. Una hoja de estilo XSLT puede declarar variables con la etiqueta <xsl:param> y también aceptarlos de fuentes externas a la hoja de estilo.

Table 50.
Atributo name value Descripción nombre del parametro valor del parametro sí no Requerido Por defecto ninguno cuerpo

Los parámetros permiten personalizar hojas de estilo. Como ejemplo, estos son los posibles parámetros [http://docbook.sourceforge.net/release/xsl/current/doc/html/] de las hojas de estilo Docbook XSL. Normalmente, los parametros XSL se añaden incluyendo una hoja de estilo que los contiene. Aqui, como en otras ocasiones, JSTL se revela adecuado solo para un uso improvisado. Ejemplo: <x:param name="draft.mode" value="no"/> Una forma equivalente a la anterior: <x:param name="draft.mode">no</x:param>

Validadores de bibliotecas (TLVs)
¿Que es un TLV?
Los TLVs (Tag Library Validators) son validadores asociados a bibliotecas de etiquetas. Antes de ejecutar cada etiqueta, el contenedor ejecuta automáticamente los TLV que tenga asociados (si existe alguno).

¿Como funciona?
• Antes de compilar un JSP, el contenedor transforma la página JSP en un documento JSP, que es 50

JSTL

la versión equivalente en XML. Ver JSP 2.0 The New Deal Part 3 [http://www.onjava.com/pub/a/onjava/2004/04/21/JSP2part3.html] acerca de esto. • El documento XML se crea con un elemento jsp:id por cada elemento de la página. Cada uno de estos ids esta referenciado desde un Map, que les asocia información (fichero, línea, y columna) que permite identificar su origen en la página JSP. Si alguna de las etiquetas del documento JSP tiene asociado un TLV, el contenedor ejecuta dicho TLV. Si el TLV detecta un error, le indica al contenedor el id del elemento erróneo. A continuación el contenedor adjunta información adicional sobre ese elemento (el fichero, línea, y columna).

• •

TLVs de JSTL
Si hemos instalado JSTL, los dos TLVs que proporciona estarán disponibles. Su implementación esta en el paquete javax.servlet.jsp.jstl.tlv [http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/package-summary.html]. Son estos: • ScriptFree: Permite restringir los elementos de scripting de una página JSP. Sus parametros son:

Table 51. Parametros de ScriptFree
parametro allowRTExpressions restringe Valores dependientes del request. Ejemplo: <c:out value="<%=request%> "/> Expresiones: <%= ... %> Scriptlets: <% ... %> Declaraciones: <%! ... %> valor por defecto true

allowExpressions allowScriptlets allowDeclarations

true true true

Su implementación es la clase ScriptFreeTLV [http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.html], y se define en el fichero tld scriptfree.tld. En JSP 2.0 también es posible usar el elemento scripting-invalid para impedir el uso de código java en las páginas JSP. • PermittedTaglibs: Permite restringir los tld a importar en una página. Su implementación es la clase PermittedTaglibsTLV [http://java.sun.com/webservices/docs/1.0/api/javax/servlet/jsp/jstl/tlv/PermittedTaglibsTLV.ht ml], y se define en el fichero tld permittedTaglibs.tld. Acepta un único parametro que contiene las uris permitidas separadas por un espacio. En el fichero permittedTaglibs.tld tiene esta configuración: <validator> <validator-class> javax.servlet.jsp.jstl.tlv.PermittedTaglibsTLV </validator-class> <init-param> <param-name>permittedTaglibs</param-name> <param-value> http://java.sun.com/jstl/core http://java.sun.com/jstl/fmt http://java.sun.com/jstl/sql http://java.sun.com/jstl/xml </param-value> 51

JSTL

<description> Whitespace-separated list of taglib URIs to permit. This example TLD for the Standard Taglib allows only JSTL 'el' taglibs to be imported. </description> </init-param> </validator>

Si queremos usarlos en nuestra biblioteca de etiquetas, podemos indicarlo en el su fichero taglib, o directamente en la página adjuntando la directiva taglib correspondiente. Por ejemplo:

<%@ taglib prefix="scriptfree" uri="http://jakarta.apache.org/taglibs/standard/s Con la línea anterior indicamos el uso de ScriptFreeTLV con los parametros que figuran en el fichero scriptfree.tld (todo a false). Si queremos personalizarlo podemos editar ese .tld y copiar el elemento validator al tld de nuestras etiquetas, ajustando los parametros según nos convenga. Las bibliotecas JSTL tienen sus propios TLVs, que no tiene sentido reutilizar pues están diseñados especificamente para validar etiquetas JSTL. Por ejemplo, la librería core usa el TLV JstlCoreTLV. Podemos verlo leyendo el fichero c.tld contenido en el jar standard-1.0.4.jar: ... <validator> <validator-class> org.apache.taglibs.standard.tlv.JstlCoreTLV </validator-class> <description> Provides core validation features for JSTL tags. </description> </validator> ... Observese que carece de parametros, porque no esta pensado para su uso por el usuario.

Repaso a XPath
Esta sección es un repaso rápido a XPath. Si quieres experimentar mientras estudias, puedes usar XPath Explorer [http://www.purpletech.com/xpe/index.jsp] de Alex Chaffe.

¿Que es XPath?
• • • • XPath es la especificación de una sintaxis con la que referirse a partes de un documento XML. XPath se usa en XSLT, XPointer, y en software de interpretación (parsing) de XML. XPath incluye funciones para trabajar con cadenas, números, y expresiones booleanas. XPath fue publicado por el W3C con categoría de “tecnología recomendada” en Noviembre de 1999.

Selección
Seleccionar nodos
Hay varias similitudes entre el sistema de ficheros unix y los documentos XML:

52

JSTL

• • • • • •

Todo documento XML tiene estructura de árbol. El separador entre padres e hijos es el caracter (/). Una referencia absoluta a un elemento comienza con el carácter (/), una referencia relativa no. El nodo actual se referencia con punto (.). El nodo padre se referencia con dos puntos (..). Para seleccionar un elemento sin tener en cuenta su nombre usamos asterisco (*).

Tomemos como ejemplo el siguiente documento XML: <?xml version="1.0" encoding="ISO-8859-1"?> <email> <from>Pedro</from> <to>Jano</to> <tema>Re:Parrillada en la montaña</tema> <cuerpo> <p color="azul"> Dile a la montaña que yo no voy. </p> Saludos, <a href="mailto:pedro@xxxxx.com">Pedro</a> </cuerpo> </email>

Table 52.
expresión /email/cuerpo/p /email/cuerpo/../cuerpo/p ./p /email/cuerpo/* /email/*/p /*/*/p //* selecciona El primer elemento párrafo (p) hijo de cuerpo. Lo mismo dando un rodeo. Lo mismo suponiendo que cuerpo sea el nodo actual. Todos los hijos del cuerpo. Todos los párrafos nietos del elemento email. Todos los párrafos nietos de la raíz. Todos los elementos.

Seleccionar a cualquier nivel
Podemos usar el operador de descenso recursivo // para referirnos a cualquier descendiente.

Table 53.
expresión //p /email/cuerpo//p selecciona Cualquier elemento p descendiente de la raíz. Cualquier elemento p descendiente del cuerpo.

Combinar varias búsquedas
Pueden combinarse varias expresiones de búsqueda con |. El resultado será todos los nodos que cumplan alguna de las dos condiciones. Ejemplo: 53

JSTL

Table 54.
expresión //p | //a selecciona Todos los párrafos y enlaces a cualquier nivel.

Filtrar con []
Podemos usar paréntesis cuadrados para especificar criterios que deben satisfacer los elementos a buscar.

Table 55.
expresión /email/cuerpo/p[1] /email/cuerpo/p[last()] /email/cuerpo[p] /email[to=Jano] /email[to=Jano]/to selecciona Primer párrafo hijo de cuerpo. En XPath el primer elemento es uno, no cero como en java. Último párrafo hijo de cuerpo (hemos usado una función XPath). Todos los elementos cuerpo hijos de email y con un elemento p. Los elementos email con hijo to igual a Jano. Todos los elementos to con contenido Jano.

Seleccionar atributos con @
En XPath los atributos se preceden con el carácter @. Para especificar los atributos de los elementos que queremos seleccionar usamos elemento[@atributo].

Table 56.
expresión //p[@color="azul"] //p[@*] //p[@color] //@color selecciona todos los párrafos con atributo color igual a rojo todos los párrafos con cero o más atributos todos los párrafos con atributo color todos los atributos color

Resumen de operadores
Table 57.
Operador * . .. @ / 54 Función Selecciona todos sus elementos sin tener en cuenta su nombre. Nodo actual. Nodo padre. Selecciona todos los atributos sin tener en cuenta su nombre. Separador entre elementos. Cuando aparece al principio indica que los hijos deben ser selec-

JSTL

Operador // [condicion]

Función cionados a partir del nodo raíz. Especifica una búsqueda sobre cualquier descendiente. Desprecia los elementos seleccionados que no cumplen la condición dada.

Ejemplos varios
Table 58.
Ejemplo . .. p //p * */p @* ../@href text() p[1] p[last()] /email/cuerpo/p[1]/a[2] a[@href="#N101AF"] div[@id="noticia"][2] div[@user="jano" or @user="jano-r"] Nodo actual. Padre del nodo actual. Hijo p del nodo actual. Todos los hijos p del nodo raíz. Cualquier hijo del nodo actual. Todos los nietos p del nodo actual. Cualquier atributo del nodo actual. Atributo href del padre del nodo actual. todos los nodos de texto del nodo actual Segundo hijo p del nodo actual (segundo hijo, no el nieto). Último hijo p del nodo actual. Segundo enlace del primer párrafo hijo del elemento cuerpo. Enlace hijo del nodo actual con atributo href igual a #N101AF. Segundo hijo div del nodo actual con atributo id igual a noticia. Todos los hijos div del nodo actual con atribute user igual a jano o jano-r. Resultado

Expresiones XPath
Son las compuestas con los operadores +, –, *, div, mod, = (igualdad), !=, <, <=, >, >=, or, and.

Métodos
Funciones Node Set
Table 59.
Nombre count() id() last() 55 Descripción Devuelve el número de elementos seleccionados. Selecciona elementos por su id único. Devuelve un número igual al tamaño del con-

JSTL

Nombre local-name()

Descripción texto donde se evalua la expresión. Devuelve la parte local del nombre expandido del nodo en el conjunto de nodos del argumento que es el primero en el orden del documento. Devuelve el nombre de un elemento. Devuelve la URI del espacio de nombres del nombre expandido del nodo en el conjunto de nodos del argumento que es el primero en el orden del documento. Devuelve un número igual a la posición del contexto desde el contexto de la expresión evaluada.

name() namespace-uri()

position()

Funciones de cadena
Table 60.
Atributo concat() Descripción Devuelve la concatenación de sus argumentos Devuelve true si la primera cadena contiene la segunda; false en caso contrario. Ejemplo concat('hola',' ','mundo') contains('hola mundo','hola') Resultado hola mundo

contains()

true

normalizespace() starts-with()

Quita espacios al comi- normalizeenzo y final. space(' hola mundo ') Devuelve true si la primera cadena comienza con la segunda, o false en caso contrario. Convierte un objeto a cadena. startswith('hola mundo','hol')

hola mundo

true

starts-with()

string(123.45)

123,45 10

string-length() Devuelve el número de stringcaracteres de una calength('hola dena. mundo') substring() substringafter() substring-before() translate() Devuelve una subcadena. substring('hola mundo',1,4)

hola mundo

Devuelve la subcadena substringtras otra subcadena. after('hola mundo',' ') Devuelve la subcadena substring-beanterior a otra subfore('hola cadena. mundo',' ') Reemplaza una cadena translate('hola por otra. mundo','a','4')

hola

hol4 mundo

Funciones numéricas

56

JSTL

Table 61.
Atributo ceiling() Descripción Ejemplo 13 Resultado Devuelve el entero más ceiling(12.3) pequeño y no menor que el argumento. Devuelve el entero más floor(12.3) grande pero no mayor que el argumento. Devuelve el número number(4) correspondiente a su argumento. Devuelve el entero más round(12.3) próximo al argumento. Devuelve la suma res- sum(.) ultante de sumar el conjunto de nodos que pasamos como parametro.

floor()

12

number()

4

round() sum()

12

Funciones booleanas
Table 62.
Atributo boolean() false() true() false() Descripción Convierte su argumento a boolean. Devuelve false Devuelve true. Devuelve true si el argumento es false y viceversa. Devuelve true. not(false()) true false() false Ejemplo Resultado

true()

true()

true

Espacios de nombres
Supongamos un documento como <?xml version="1.0" encoding="ISO-8859-1"?> <email:email> <email:tema>Re:Parrillada en la montaña</email:tema> <email:cuerpo> Dile a la montaña que yo no voy. <binary:attachment>GIF89ahÈ00WW¤3u¸Côéð...</binary:attachment> </email:cuerpo> </email:email> ¿Cómo accedemos a binary:attachment? • • /email/cuerpo/attachment no es correcto porque ignora el espacio de nombres /email:email/email:cuerpo/email:attachment no es correcto porque los espa57

JSTL

cios de nombres (que son sinónimos de sus respectivas URIs) los usa internamente el documento pero no podemos usarlos nosotros. • • Una manera sencilla es //*[name()='attachment'] Otra manera más especifica es / *[name()='email']/*[name()='cuerpo']/*[name()='attachment']

58

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->