Introducción A JSTL
Introducción A JSTL
Introducción A JSTL
Introduccin a JSTL
JSTL responde a la demanda de los desarrolladores de un conjunto de acciones JSP personalizadas para manejar las tareas que necesitan casi todas las pginas JSP, incluyendo procesamiento condicional, internacionalizacin, acceso a bases de datos y procesamiento XML. Esto acelarar el desarrollo de JSPs ms o menos eliminando la necesidad de elementos de scripting y los inevitables y difciles de encontrar errores de sintaxis, y liberando el tiempo anteriormente gastado en desarrollar y aprender trillones de acciones personalizadas especficas del proyecto para estas tareas comunes. Este tutorial nos ensea cmo JSTL puede simplificar nuestra vida cuando usamos JSP, en grandes y pequeas aplicaciones. En este tutorial se ofrecer una introduccin a JSTL y mostrar como usar las acctiones JSTL ms comunes.
La Librera Core contiene acciones para las tareas rutinarias, como incluir o excluir una parte de una pgina dependiendo de una condicin en tiempo de ejecucin, hacer un bucle sobre una coleccin de tems, manipular URLs para seguimiento de sesin, y la correcta interpretacin del recurso objetivo, as como acciones para importar contenido de otros recursos y redireccionar la respuesta a una URL diferente. La Librera XML contiene acciones -- como puedes imaginar -- para procesamiento XML, includo validar un documento XML y transformarlo usando XSLT. Tambin proporciona acciones para extraer parte de un documento XML validado, hacer bucles sobre un conjunto de nodos, y procesamiendo condicional basado en valores de nodos.
La Internationalizacin (i18n) y el formateo general estn soportados por las acciones de la Librera I18N & Formatting. Podemos leer y modificar informacin almacenada en una base de datos con las acciones proporcionadas por la Librera Database Access. Ms adelante, podemos esperar que todos los contenedores Web incluyan una implementacin de las libreras JSTL, as no tendremos que instalar ningn cdigo adicional. Hasta que esto suceda, podemos descargar e instalar la implementacin de referencia (RI) de JSTL. Se ha desarrollado dentro del proyecto Apache Taglibs como una librera llamada Standard. Puedes bajarla desde aqu:The JSTL RI: the Standard Library at Apache Taglibs. Instalar RI es fcil, slo hay que copiar los ficheros JAR del directorio lib de la distribucin al directorio WEB-INF/lib de nuestra aplicacin. Observa que JSTL 1.0 requiere un contenedor JSP 1.2, debemos asegurarnos de tener un contenedor compatible con JSP 1.2 antes de probar esto. Para usar una librera JSTL, tanto si la implementacin est incluida con el contenedor o con el RI, debemos declarar la librera usando una directiva taglib, como lo haramos con una librera de etiquetas personalizadas normal:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
Observa que siempre deberamos usar la URI por defecto, incluso aunque la especificacin JSP nos permita sobreescribirla. Un contenedor puede generar cdigo optimizado para la accin JSTL en la clase correspondiente a una pgina JSP. Esto puede resultar en un mejor rendimiento que cuando el cdigo generado llama a los manejadores de etiquetas a travs del API estndar. Sin embargo, slo cuando se usa la URI por defecto, es cuando el contenedor puede utilizar una implementacin optimizada.
Como se ve aqu, una exprein EL siempre debe estar encerrada entre los caracteres ${ y }$. Las dos primera expresiones acceden a una propiedad llamada myProperty en un objeto representado por una variable llamada myObj. La tercera expresin acceder a una propiedad con un nombre contenido en un variable, esta sintaxis se puede utilizar con cualquier expresin que evale el nombre de la propiedad. El operador de acceso a array tambin se usa para datos representados como una coleccin de elementos indexados, como un array Java o una java.util.List:
${myList[2]}$ ${myList[aVar + 1]}$
Adems de los operadores de propiedad y elemento array y los operadores aritmticos, relacionales, y lgicos, hay un operador especial para comprobar si un objeto est "vaco" o no puede ser usado en una expresin EL. La siguiente tabla lista todos los operadores: Operador
. [] () + / %
Description Accede a una propiedad Accede a un elemento de un array/lista Agrupa una subexpression Suma Resta o negacin de un nmero
o div o mod o eq o ne
Divisin Mdulo (resto) Comprueba Igualdad Comprueba desigualdad Comprueba menor que Comprueba mayor que Comprueba menor o igual que Comprueba mayor o igual que Comrpueba AND lgico Comprueba OR lgico Complemento binario booleano Comprueba un valor vaco (null, string vaco, o una colleccin vaca)
== != < >
o lt o gt o le o gt o and o or
o not
empty
Lo que no encontraremos en EL son sentencias como asignaciones, if/else, o while. Para este tipo de funcionalidades en JSP se usan los elementos Action, y EL no est pensado para utilizarse como un lenguaje de programacin de propsito generar, slo un lenguaje de acceso a datos. Por supuesto, los literales y las variables, tambin son parte del lenguaje. EL proporciona los siguientes literales, similares a los que proporcionan JavaScript, Java, y otros lenguajes similares: Tipo de Literal Descripcin Encerrado con comillas simples o dobles. Una comilla del mismo tipo dentro del string puede ser escapada con una barra invertida: (\' en un string encerrado con comillas simples; \" en un string encerrado con comillas dobles). El caracter de barra invertida debe se escapado como \\ en ambos casos. Un signo opcional (+ o -) seguido por digitos entre 0 y 9. Lo mismo que un literal entero, excepto que usa un punto como separador de la parte fraccional y que se puede especificar un exponente con e o E, seguido por un literal entero.
true null.
String
o false.
Cualquier objeto en uno de los mbitos de JSP (pgina, solicitud, sesin o aplicacin) se puede utilizar como una variable en una expresin EL. Por ejemplo, si tenemos un bean con una propiedad firstName en el mbito de la solicitud bajo el nombre customer, esta expresin EL representa el valor de la propiedad firstName del bean.
${customer.firstName}
Pero no se para aqu. EL tambin hace que la informacin de la solicitud y la informacin general del contenedor est disponible como un conjunto de variables implcitas: Variable
param paramValues header headerValues cookie
Descripcin Una collection de todos de los parmetros de la solicitud como un slo valor string para cada parmetro. Una collection de todos los valores de los parmetros de la solicitud como un array de valores string por cada parmetro. Una collection de todas las cabeceras de solicitud como un slo valor string por cada cabecera. Una collection de todos los valores de cabecera de la solicitud como un array de valores string por cada cabecera. Una collection con todas las cookies de la solicitud en un slo ejemplar de javax.servlet.http.Cookie por cada cokkie.
Una collection de todos los parmetros de inicializacin de la aplicacin en un slo valor string por cada parmetro. Un ejemplar de la clase javax.servlet.jspPageContext. Una collection de todos los objetos en el mbito de la pgina. Una collection de todos los objetos en el mbito de la solicitud. Una collection de todos los objetos en el mbito de la sesin. Una collection de todos los objetos en el mbito de la aplicacin.
Las cinco primeras variables implcitas de la tabla nos ofrecen acceso a los valores de parmetros, cabeceras y cookies de la solicitud actual. Aqu hay un ejemplo de cmo acceder a un parmetro de solicitud llamado listType y a la cabecera User-Agent:
${param.listType} ${header['User-Agent']}
Observa como debemos usar la sintaxis de array para la cabecera, porque el nombre incluye un guin; con la sintaxis de propiedad, sera interpretado como la expresin vairable header.User menos el valor de una variable llamada Agent. La variable initParameter proporciona acceso a los parmetros de inicializacin que se definen en el fichero web.xml de la aplicacin. La variable pageContext tiene varias propiedades que proporcionan acceso al objeto servlet que representa la solicitud, la respuesta, la sesin y la aplicacin, etc. Las cuatro ltimas variables son colecciones que contienen todos los objetos de cada mbito especfico. Podemos usarlas para limitar la bsqueda de un objeto en slo un mbito en lugar de buscar en todos ellos, lo que est por defecto si no se especifica ningn mbito. En otras palabras, si hay un objeto llamado customer en el mbito de sesin, estas dos primeras expresiones encuentran el mismo objeto, pero la tercera vuelve vaca:
${customer} ${sessionScope.customer} ${requestScope.customer}
Todas las acciones JSTL aceptan expresiones EL como valores de atributo, para todos los atributos excepto para var y scope, porque estos valores de atributo podran usarse para chequear el tipo en el momento de la traduccin en una futura versin. Hay un atributo de una accin JSTL adicional que no toma un valor de expresin EL, pero slo se usa en la librera XML, por eso lo ignoraremos por ahora. Se pueden usan una o ms expresiones EL en el mismo valor de atributo, y el texto fijo y las expresiones EL se pueden mezclar en el mismo valor de atributo:
First name: <c:out value="${customer.firstName}" /> <c:out value="First name: ${customer.firstName}" />
Antes de saltar a ver ejemplos de utilizacin de las acciones Core, dejme cualificar algo que dijimos anteriormente: todas las acciones JSTL de la librera EL aceptan expresiones EL. Realmente hay un conjunto parelelo de libreras JSTL, llamado conjunto de librera RT. que slo acepta expresiones Java del viejo estilo:
First name: <c_rt:out value="<%= customer.getFirstName() %>" />
nos permite incluir, o procesar, condicionalmente una parte de una pgina, dependiendo de la informacin durante la ejecucin. Este ejemplo incluye un saludo personal si el usuario es un visitante repetitivo, segn lo indica la presencia de una cokkie con el nombre del usuario:
<c:if test="${!empty cookie.userName}"> Welcome back <c:out value="${cookie.userName.value}" /> </c:if>
El valor del atributo test es una expresin EL que chequea si la cookie existe. El operador empty combinado con el operador "not" (!) significa que evala a true si el cookie no existe, haciendo que el cuerpo del elemento sea procesado. Dentro del cuerpo, la accin <c:out> aade el valor de la cookie a la respuesta. As de sencillo. Pasar a travs de una coleccin de datos es casi tan sencillo. Este fragmento itera sobre una coleccin de filas de una base de datos con informacin del tiempo de diferentes ciudades:
<c:forEach items="${forecasts.rows}" var="${city}"> City: <c:out value="${city.name}" /> Tomorrow's high: <c:out value="${city.high}" /> Tomorrow's low: <c:out value="${city.low}" /> </c:forEach>
La expresin EL para el valor items obtiene el valor de la propiedad rows desde un objeto representado por la variable forecasts. Como aprenderemos ms adelante, la acciones de bases de datos de JSTL representan un resultado de consulta como un ejemplar de una clase llamada javax.servlet.jsp.jstl.sql.Result. Esta clase se puede utilizar como un bean con varias propiedades. La propiedad rows contiene un array de ejemplares java.util.SortedMap, donde cada uno representa una fila con valores de columnas. La accin <c:forEach> procesa su cuerpo una vez por cada elemento de la coleccin especificado por el atributo items. Adems de con arrays, la
accin funciona con cualquier otro tipo de dato que represente una coleccin, como ejemplares de las clases java.util.Collection o java.util.Map. Si se especifica el atributo var, el elemento actual de la coleccin se hace disponible para las acciones del cuerpo como una variable con el nombre especificado. Aqu se llamaba city y, como la coleccin es un array de maps, esta variable contiene un nuevo map con valores de columnas cada vez que se procesa el cuerpo. Los valores de las columnas se aaden a la respuesta por el mismo tipo de acciones <c:out> que hemos visto en ejemplos anteriores. Para ilustrar el uso del resto de las acciones condicionales, extendamos el ejemplo de iteraccin para procesar slo un conjunto fijo de filas por cada pgina solicitada, aadamos enlaces "Previous" y "Next" a la misma pgina. El usuario puede entonces pasar sobre los resultados de la base de datos, mirando unas pocas fila cada vez, asumiendo que el objeto Result se ha grabado en el mbito de la sesin. Aqu est cmo procesar slo algunas filas:
<c:set var="noOfRows" value="10" /> <c:forEach items="${forecasts.rows}" var="${city}" begin="${param.first}" end="${param.first + noOfRows - 1}"> City: <c:out value="${city.name}" /> Tomorrow's high: <c:out value="${city.high}" /> Tomorrow's low: <c:out value="${city.low}" /> </c:forEach>
La accin <c:set> selecciona una variable con el valor especificado por el atributo value; que puede ser un valor esttico, como en este ejemplo, o una expresin EL. Tambin podemos especificar el mbito de la variable con el atributo scope (page, request, session o application). En este ejemplo, hemos seleccionado una variable llamada noOfRows a 10 en el mbito de la pgina (por defecto). Este es el nmero de filas que mostraremos en cada solicitud. El <c:forEach> en este ejemplo toma los mismos valores para los atributos items y var como antes, pero hemos aadido dos nuevos atributos:
El atributo begin toma el ndice (base 0) del primer elemento de la coleccin a procesar. Aqu se selecciona al valor de un parmetro de solicitud llamado first. Para la primera solicitud, este parmetro no est disponible, por eso la expresin se evala a 0; en otras palabtas, la primea fila. El atributo end especifica el ndice del ltimo elemento de la coleccin a procesar. Aqu lo hemos seleccionado al valor del parmetro first ms noOfRows menos uno. Para la primera solicitud, cuando no existe el parmetro de la solicitud, este resultado es 9, por eso la accin itera sobre los ndices del 0 al 9.
Previous Page</a> </c:when> <c:otherwise> Previous Page </c:otherwise> </c:choose> <c:choose> <c:when test="${param.first + noOfRows < forecasts.rowsCount}"> <a href="foreach.jsp?first=<c:out value="${param.first + noOfRows}"/>"> Next Page</a> </c:when> <c:otherwise> Next Page </c:otherwise> </c:choose>
El <c:choose> agrupa una o ms acciones <c:when>, cada una especificando una condicin booleana diferente. La accin <c:choose> chequea cada condicin en orden y slo permite la primera accin <c:choose> con una condicin que se evale a true para procesar su cuerpo. El cuerpo <c:choose> tambin podra contener un <c:otherwise>. Su cuerpo slo se procesa si ninguna de las condiciones de los <c:when> es true. En este ejemplo, la primera accin <c:when> comprueba si el parmetro first es mayor que cero, es decir, si la pgina muestra un subconjunto de filas distinto del primero. Si esto es cierto, el cuerpo de la accin <c:when> aade un enlace a la misma pgina con un parmetro first seleccionado al ndice del subconjunto anterior. Si no es true, se procesa el cuerpo de la accin <c:otherwise>, aadiendo slo el texto "Previous Page". El segundo bloque <c:choose> proporciona lgica similar para aadir el enlace "Next Page".
Procesar URLs
Los ejemplos anteriores funcionan bien mientras se utilicen las cookies para seguimiento de sesin. No est todo dado; el navegador podra tener desactivadas las cookies, o no soportarlas. Por lo tanto es una buena idea activar el contenedor para usar la reescritura de URL como backup de los cookies. La reescritura de URL, como podras conocer, significa poner el ID de la sesin en todas las URLs usadas en los enlaces y formularios de la pgina. Una URL reescrita se parece a algo como esto:
myPage.jsp;jspsessionid=ah3bf5e317xmw5
Cuando el usuario pulsa en una lnea como esta, el identificador de sesin ID se enva al contenedor como parte de la URL. La librera corazn de JSTL incluye la accin <c:url>, que tiene cuidado de la reescritura de URL por nosotros. Aqu est como podemos usarla para mejorar la generacin del enlace "Previous Page" del ejemplo anterior:
<c:url var="previous" value="foreach.jsp"> <c:param name="first" value="${param.first - noOfRows}" /> </c:url> <a href="<c:out value="${previous}"/>">Previous Page</a>
<c:url>
soporta un atributo var, usado para especificar una variable para contener la URL codificada, y un atributo value para contener la URL a codificar. Se pueden especificar parmetros string para solicitar la URL usando acciones <c:param>. Los caracteres especiales en los parmetros especificados por elementos anidados son codificados (si es necesario) y luego aadidos a la URL como parmetros string de la consulta. El resultado final se pasa a travs del proceso de reescritura de URL, aadiendo un ID de sesin si est desactivado el seguimiento de sesin usando cookies. En este ejemplo, se utiliza la URL codificada como un valor de atributo href en un elemento de enlace HTML.
<c:url>
tambin realiza otro buen servicio. Como podra preocuparte, las URLs relativas en elementos HTML tambin deben ser relativas a la pgina que los contiene o al directorio raz del servidor (si empiezan con una barra inclinada). La primera parte del path de una URL de una pgina JSP se llama path de contexto, y podra variar de instalacin a instalacin. Por lo tanto deberamos evitar codificar el path de contexto en las pginas JSP. Pero algunas veces realmente querremos utilizar un path de URL relativo al servidor en elemento HTML; por ejemplo cuando necesitamos referirnos a un fichero de imagen localizado en el directorio /images compartido por todas las pginas JSP. Las buenas noticias es que si especificamos una URL con un barra inclinada como el valor <c:url>, lo convierte en un path relativo al servidor. Por ejemplo, en una aplicacin con el path de contexto /myApp, la accin <c:url> convierte el path a /myApp/images/logo.gif:
<c:url value="/images/logo.gif" />
Hay unas cuantas acciones ms relacionadas con las URLs en la librera corazn. La accin <c:import> es una accin ms flexible que la accin estndar <jsp:include>. Podemos usarla para incluir contenido desde los recursos dentro de la misma aplicacin Web, desde otras aplicaciones Web en el mismo contenedor, o desde otros servidores, usando protocolos como HTTP y FTP. La accion <c:redirect> nos permite redirigir a otro recurso en la misma aplicacin Web, en otra aplicacin Web o en un servidor diferente. Ambas acciones son fciles de usar, por eso te dejamos como ejercicio que las prctiques.
Internacionalizacin y Formateo o Formateo de Fechas y Nmeros Sensible a la Localidad o Usar JSTL para Seleccionar la Localidad o Usar un Controlador para Selecciona la Localidad o Generar Texto Localizado
Internacionalizacin y Formateo
Las grandes sites normalmente necesitan complacer a los visitantes de todo el mundo, y servir el contenido slo en un idioma no es suficiente. Para desarrollar una site que proporcione una eleccin de idiomas, tenemos dos opciones:
Escribir un conjunto de pginas para cada idioma. Escribir un conjunto compartido de pginas que ponga el contenido en diferentes idiomas desde fuentes externas.
Frecuentemente terminaremos con una mezcla de estas tcnicas, usar pginas separadas para la mayora de las grandes cantidades de contenido esttico y pginas compartidas cuando la cantidad de contenido sea pequea pero dinmica (por ejemplo, una pgina con unas pocas etiquetas fijas mostradas en diferentes idiomas y todos los dems datos que vengan desde una base de datos). Preparar una aplicacin para varios idiomas se llama internacionalizacin (comunmente abreviado i18n) y hacer que el contenido est disponible para un idioma especfico se llama localizacin (o l10n). Para hacer esto necesitamos considerar otras cosas adems del idioma. Cmo se formatean las fechas y nmeros entre los diferentes pases, e incluso dentro de los pases. Tambin podramos necesitar adaptar los colores, las imgenes y otro contenido no textual. El trmino localidad se refiere a un conjunto de reglas y contenido aceptable para una regin o cultura.
La primera lnea es la directiva taglib para la librera JSTL que contiene las acciones de formateo e internacionalizacin. El prefijo por defecto, usado aqu, es fmt. Para obtener un valor a formatear, entonces crea un objeto java.util.Date que representa la fecha y hora actuales, y lo graba como una variable llamada now. Ya estamos preparados para hacer algn formateo sensible a la localidad. La accin JSTL <fmt:formatDate> formatea el valor de la variable now asignado al valor del atributo value usando el tipo de expresin EL que aprendimos en la pgina anterior. El atributo dateStyle le dice a la accin cmo debe formatear la fecha. Podemos usar cualquiera de los valores default, short, medium, long, o full para el atributo dateStyle. El tipo de formateo que representa cada uno de estos tipos depende exactamente de la localidad. Para la localidad English, full resulta en un string como Thursday, August 29, 2002. En este ejemplo, slo hemos formateado la parte de la fecha, pero tambin podemos incluir la parte de la hora (o formatear slo la hora), y
definir reglas de formateo personalizadas tanto para la fecha como para la hora en lugar de los estilos dependientes de la localidad:
<fmt:formatDate value="${now}" type="both" pattern="EEEE, dd MMMM yyyy, HH:mm" />
El atributo pattern toma un patrn de formateo personalizado del mismo tipo que la clase java.text.SimpleDateFormat. El patrn usado aqu resulta en Thursday, 29 August 2002, 17:29 con la localidad English. La accin <fmt:formatNumber> soporta atributos similares para especificar cmo formatear un nmero usando estilos dependientes de la localidad para nmeros normales, valores de moneda, o un porcentaje, as como usar patrones personalizados de diferentes tipos.
Con esta seleccin, se usar la localidad German (especificada por el cdigo de idioma de como valor de parmetro) si ninguna de las localidades especificadas por la solicitud est soportada por el entorno Java. JSTL tambin nos permite seleccionar una localidad por defecto para la aplicacin que podremos sobreescribir cuando lo necesitemos. Esto nos da control total sobre la localidad a utilizar, en lugar de dejarlo a la configuracin del navegador del visitante. La
localidad por defecto tambin es una seleccin de configuracin. Se puede especificar con un parmetro de contexto en el fichero web.xml de esta forma:
<context-param> <param-name> javax.servlet.jsp.jstl.fmt.locale </param-name> <param-value> en </param-value> </context-param>
Esta seleccin establece English como la localidad por defecto, resultando en la anterior pgina JSP siempre formatear la fecha y los nmeros de acuerdo a las reglas inglesas. Para sobreescribir la configuracin del localidad por defecto, podemos usar la accin <fmt:setLocale>. Selecciona la localidad por defeco dentro de un mbito JSP especfico. Aqu tenemos un ejemplo que selecciona la localidad por defecto del mbito de la pgina, basndose en una cookie que sigue la pista de la localidad seleccionada por el usuario en una visita anterior:
<h1>Formatting with a locale set by setLocale</h1> <c:if test="${!empty cookie.preferredLocale}"> <fmt:setLocale value="${cookie.preferredLocale.value}" /> </c:if> <jsp:useBean id="now" class="java.util.Date" /> Date: <fmt:formatDate value="${now}" dateStyle="full" /> Number: <fmt:formatNumber value="${now.time}" />
Aqu, primero hemos usado la accin JSTL <c:if> para comprobar si con la solicitud se ha recibido una cookie llamada preferredLocale. Si es as, la accin <fmt:setLocale> sobreescribe la localidad para la pgina actual seleccionan la variable de configuracin de la localidad en el mbito de la pgina. Si lo queremos, podemos seleccionar la localidad para otro mbito usando el atributo scope. Finalmente, se formatean la fecha y el nmero de acuerdo a las reglas de la localidad especificada por la cookie, o la localidad por defecto, si la cookie no est presente. Adems de acciones para formateo, JSTL incluye acciones para interpretar (analizar) fechas y nmero de una forma sensible a la localidad: <fmt:parseDate> y <fmt:parseNumber>. Estas acciones soportan casi todos los mismos atributos que sus contrapartidas de formateo, y se pueden utilizar para convertir entradas de fechas y nmeros en sus formas nativas antes de procesarlas.
la Vista y el Modelo). Struts proporciona un servlet Controlador genrico que delega el procesamiento especfico de tipos especficos de solicitudes a classes llamadas clases Action, y luego usa una pgina JSP especificada por la Action para generar la respuesta. JSTL est diseado para jugar bien en una aplicacin basada en MVC exponiendo una clase que puede ser utilizada por cualquier componente Java, como una clase Action de Struts, para acceder a las variables de configuracin usadas por las acciones JSTL en las pginas JSP que representan la Vista. La clase se llama javax.servlet.jsp.jstl.core.Config y contiene constantes ( variables static final String) para todas las variables de configuracin, y mtodos para seleccionar, obtener y eliminar las variables en diferentes mbitos JSP. Podemos usar cdigo como este en una clase Action de Struts para seleccionar la localidad por defecto para la sessin, basado en un prfil de datos, cuando un usuario entra en la aplicacin:
import javax.servlet.jsp.jstl.core.Config; ... public class LoginAction extends Action { public ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); ... User user = authenticate(userName, password); if (user != null) { /* * Valid user. Set the default locale in the session * to the user's preferred locale */ HttpSession session = request.getSession(); Config.set(session, Config.FMT_LOCALE, user.getLocale()); ... } } }
La clase Config proporciona cuatro mtodos set(), uno por cada mbito JSP (especificado por el primer parmetro de mtodo). Aqu hemos usado el que selecciona la variable en el mbito de sesin. El segundo parmetro es el nombre de la configuracin, tpicamente seleccionado por la constante correspondiente. El tercer parmetro es el valor de la variable. Para leer y eliminar variable, la clase proporciona mtodos get() y remove() similares, ms un mtodo find() para localizar una variable en cualquier mbito. Adems de usar estos mtodos en un Controlador, podramos querer usarlos en nuestro propios manejadores de etiquetas personalizados para aprovecharnos de los mecanismos de configuracin JSTL.
por eso trata con el soporte genrico de i18n de la plataforma Java. Cuando viene con texto, este soporte est basado en lo que se llama un paquete de recursos. En su forma ms simple, un paquete de recursos est representado por un fichero de texto que contiene claves y un valor de texto para cada clave. Este ejemplo muestra un fichero con dos claves (hello y goodbye) y sus valores:
hello=Hello goodbye=Goodbye
Las distintas localidades se soportan creando ficheros separados para cada una de ellas, con un nombre de fichero que incluye el nombre de la localidad. Por ejemplo, si el fichero del paquete de recursos anterior representa la localidad English, debera almacenarse en un fichero llamado labels_en.properties. El paquete de recursos para la localidad Swedish sera almacenado en un fichero llamado labels_sv.properties, donde sv es el cdigo de idioma. La parte fija del nombre de fichero, labels de este ejemplo, se llama el nombre base del paquete de recursos, y se combina con una especificacin de localidad (como un cdigo de idioma) para encontrar el paquete de recursos para una localidad especfica. Todos los paquetes de recursos incluyen las mismas claves; slo difiere el texto dependiendo de la localidad. Los ficheros deben situarse en un directorio que sea parte del classpath del contenedor, normalmente el directorio WEB-INF/classes de la aplicacin. La accin JSTL que aade texto desde un paquete de recursos a una pgina es <fmt:message>. El paquete a utilizar puede especificarse de varias formas. Una es anidar las acciones <fmt:message> dentro del cuerpo de una accin <fmt:bundle>:
<fmt:bundle basename="labels"> Hello: <fmt:message key="hello" /> Goodbye: <fmt:message key="goodbye" /> </fmt:bundle>
En este caso, la accin <fmt:bundle> localiza el paquete de la localidad que es la correspondencia ms cercana entre la seleccin de configuracin de la localidad (o las localidades en el cabecera Accept-Language, si no hay localidad por defecto) y los paquetes de recursos disponibles para el nombre base especificado. Las acciones anidadas obtienen el texto desde el paquete por la clave asociada. Al igual que con las acciones de formateo, podemos establecer un paquete por defecto, para toda la aplicacin con un parmetro de contexto o con la accin <fmt:setBundle> o la clase Config para un mbito JSP especfico:
<fmt:setBundle basename="labels"/> ... Hello: <fmt:message key="hello" /> Goodbye: <fmt:message key="goodbye" />
Despus de que se haya definido un paquete por defecto, podemos usar acciones <fmt:message> independientes dentro del mbito donde se estableci el valor por defecto.
Acceder a una Base de Datos o Poner un objeto DataSource a Disposicin de JSTL o Leer Datos de la Base de Datos o Escribir Datos en la Base de Datos
Se deben utilizar las herramientas de configuracin JNDI del contenedor WEB para configurar un recurso JNDI con el nombre especificado; por ejemplo, con un nombre de usuario y una password de una cuenta de usuario en una base de datos, las conexiones mnimas y mximas en el almacen, etc. La forma de realizar esto vara entre los contenedores y est fuera del mbito de este artculo. Una alternativa para los contenedores que no soportan JNDI es que un oyente del ciclo de vida de la aplicacin (contexto del servlet) cree y configure un DataSource y lo seleccione como el valor por defeto usando la clase Config de JSTL:
import javax.servlet.*; import javax.servlet.http.*; import oracle.jdbc.pool.*; public class AppListener implements ServletContextListener { private OracleConnectionCacheImpl ds =null; public void contextInitialized(ServletContextEvent sce){ ServletContext application =sce.getServletContext(); try { ds = new OracleConnectionCacheImpl(); ds.setURL("jdbc:oracle:thin:@voyager2:1521:Oracle9i"); ds.setMaxLimit(20); ds.setUser("scott"); ds.setPassword("tiger"); } catch (Exception e){ application.log("Failed to create data source:"+ e.getMessage()); } Config.set(application, Config.SQL_DATASOURCE, ds); } ... }
La clase oyente de este ejemplo crea un DataSource con capacidades de almacen de conexiones para un base de datos Oracle9i, y la hace disponible como por defecto para las acciones JSTL usando la clase Config para seleccionar la variable de configuracin correspondiente. Una tercera forma, slo disponible para prototipos o aplicaciones que no van a utilizarse tan duramente como para necesitar el almacen de conexiones, es usar la accin <sql:setDataSource>:
<sql:setDataSource url="jdbc:mysql://dbserver/dbname" driver="org.gjt.mm.mysql.Driver" user="scott" password="tiger" />
Esta accin crea una sencilla fuente de datos, sin almacenamiento, para la URL JDBC especificada, con el usuario y la password, usando el driver JDBC especificado. Podramos usar esta accin para empezar, pero recomendamos la utilizacin de una de las otras alternativas para una site del mundo real. Adems de privarnos del almacen de
conexiones para una fuente de datos creada de esta forma, no es una buena idea incluir informacin sensible como la URL de la base de datos, el nombre de usuario y la password en una pgina JSP, ya que sera posible para alguien acceder al cdigo fuente de la pgina.
Primero necesitamos declarar la librera JSTL que contiene las acciones de bases de datos, usando la directiva taglib de la parte superior de este ejemplo. La accin <sql:query> ejecuta la sentencia SQL SELECT especificada por el atributo sql (o como el cuerpo del elemento accin) y graba los resultados en una variable nombrada por el atributo var. El resultado de la consulta a la base de datos se devuelve como un bean del tipo javax.servlet.jsp.jstl.sql.Result con varias propiedades de slo lectura: Propiedad Tipo Java Descripcin
rows
Un array con un mapa insensible a las maysculas por cada fila con las claves java.util.SortedMap[] correspondiendo con los nombres de columna y valores correspondiendo con los valores de columna.
Object[][] String[] int
Un array con un array por fila con valores de columna. Un array con nombres de columnas El nmero de filas en el resultado.
true
limitedByMaxRows boolean
si no se han incluido todas las filas debido a que se ha alcanzado el lmite mximo de filas especificado.
Ya vimos como utilizar la accin <c:forEach> para mostrar todas o slo algunas filas en la primera pgina de este tutorial, por eso ahora veremos como podemos obtener slo algunas filas para mostrarlas todas en esta parte. Los enlaces Next y Previous le
permiten al usuario solicitar un conjunto diferente. Primero, aqu est cmo leer un subconjunto de filas y luego mostrar el subconjunto completo:
<c:set var="noOfRows" value="10" /> <sql:query var="emps" startRow="${param.start}" maxRows="${noOfRows}"> SELECT * FROM Employee </sql:query> <ul> <c:forEach items="${emps.rows}" var="${emp}"> <li><c:out value="${emp.name}" /> </c:forEach> </ul>
El atributo startRow para la accin <sql:query> se enva a una expresin EL que lee el valor de un parmetro de solicitud llamado start. Pronto veremos como cambia este valor cuando se pulsa sobre los enlaces Next y Previous. La primera vez que se accede a la pgina, el parmetro no existe, por eso la expresin se evala a 0. Esto significa que el resultado de la consulta contiene filas empezando con la primera que corresponda (ndice 0). El atributo maxRows lmita el nmero total de filas del valor de la variable noOfRows, lo seleccionamos a 10 en este ejemplo. La accin <c:forEach> hace un bucle sobre todas las columnas del resultado y genera una lista de tems con los valores de columna por cada fila. Tambin debemos generar los enlaces Next y Previous para permitir que el usuario seleccione un nuevo conjunto de filas:
<c:choose> <c:when test="${param.start > 0}"> <a href="emplist.jsp?start=<c:out value="${param.start - noOfRows}"/>">Previous Page</a> </c:when> <c:otherwise> Previous Page </c:otherwise> </c:choose> <c:choose> <c:when test="${emps.limitedByMaxRows}"> <a href="emplist.jsp?start=<c:out value="${param.start + noOfRows}"/>">Next Page</a> </c:when> <c:otherwise> Next Page </c:otherwise> </c:choose>
El primer bloque <c:choose> es idntico al de la pgina 1; si el parmetro de la solicitud start es mayor que cero, la pgina actual muestra un subconjunto de filas distinto del primero, por eso se aade un enlace Previous. El enlace apunta hacia la misma pgina, e incluye el parmetro start con un valor que es el valor actual menos el nmero de filas mostrado por cada pgina.
El segundo bloque <c:choose> se aprovecha de la propiedad limitedByMaxRows del resultado de la consulta. Si esta propiedad es true, significa que se ha truncado el resultado al nmero de filas mostrado por cada pgina. De aqu, se genera el enlace Next con valor del parmetro start para el nuevo subconjunto de filas.
Antes de insertar la fila, este ejemplo ilustra cmo usar las acciones de validacin JSTL, como prometimos anteriormente. La pagina espera que todos los datos para la nueva fila se enven como parmetros de solicitud (quizs introducidos en un formulario HTML), incluyendo una fecha de contratacin. antes de que la fecha se pueda insertar en la base de datos, debemos convertirla a su forma nativa Java. Esto es lo que hace la accin <fmt:parseDate>. El atributo value contiene una expresin EL que obtiene el valor del parmatro de solicitud empDate. Al accin trata de interpretarlo como una fecha escrita en el formato especificado por el atributo pattern (un ao de cuatro dgitos, seguido por dos dgitos del ms y dos dgitos del da, separados por barras inclinadas). Si tiene xito, almacena la fecha en su forma nativa con el nombre especificado por el atributo var La accin <c:catch> tiene en cuenta los strings invlidos. Si el valor del parmetro no puede ser interpretado como una fecha, el <fmt:parseDate> lanza una excepcin, que la accin <c:catch> captura y graba en la variable especificada. Cuando esto sucede, la condicin de comprobacin de la accin <c:if> se evala a true, por lo que fecha de contratacin es creada por la accin <jsp:useBean> anidada. Para insertar la fila, usamos la accin <sql:update>. Como la accin de consulta, la sentencia SQL se puede especificar como el cuerpo del elemento o mediante un atributo sql. La accin <sql:update> se puede usar para ejecutar sentencias INSERT, UPDATE, DELETE, asi como sentencias para crear o eliminar objetos en la base de datos, como CREATE TABLE y DROP TABLE. El nmero de filas afectado por la sentencia puede capturarse de forma opcional en una variable nombrada por el atributo var.
En este ejemplo (como en las mayora de las aplicaciones del mundo real), no se conocen los nombres de las columnas en tiempo de ejecucin; vienen de los parmetros de la solicitud. Por lo tanto, la sentencia INSERT de SQL incluye una marca de interrogacin por cada valor como un contenedor y parmetros internos de la accin que seleccionan el valor dinmicamente. Las columnas FirstName y LastName son columnas de texto y las aciones <sql:param> seleccionan sus valores al valor del parmetro de solicitud correspondiente. Sin embargo, la columna EmpDate, es una columna de fecha, demandando una atencin especial. Primero de todo, debemos usar una variable que contenga la fecha en su forma nativa (un objeto java.util.Date) en lugar de usar el valor del parmetro de solicitud, usamos la variable crada por las acciones <fmt:parseDate> o <jsp:useBean>. Segundo, debemos usar la accin <sql:dateParam> para seleccionar el valor. En este ejemplo, hemos usado la parte de la fecha, por eso hemos seleccionado el atributo opcional type a date. Otros valores vlidos son time y timestamp (por defecto), para las columnas que slo toman la hora o la fecha y la hora. Hay una accin JSTL ms que no hemos descrito hasta ahora: <sql:transaction>. Podemos usarla para agrupar varias acciones update (o incluso query) donde todas ellas se deben ejecutar como parte de la misma transacin de la base de datos. El ejemplo estndard es transferir una cantidad de dinero de una cuenta a otra; implementada como una sentencia SQL que elimina el dinero de la primera cuenta y otra sentencia que lo aade a la segunda. Si encapsulamos todos los accesos a una base de datos en clases Java en lugar de usar las acciones de JSTL, todava hay una parte de JSTL que nos puede ser til. Es una clase llamada javax.servlet.jsp.jstl.sql.ResultSupport, con estos dos mtodos:
public static Result toResult(java.sql.ResultSet rs); public static Result toResult(java.sql.ResultSet rs, int maxRows);
Podemos usar esta clase para convertir un objeto ResultSet estndar JDBC en un objeto Result JSTL antes de reenviarlo a la pgina JSP para mostrarlo. Las acciones JSTL pueden acceder fcilmente a los datos de un objeto Result, como vimos anteriormente. Otra aproximacin, todava mejor, es pasar el resultado de la consulta a la pgina JSP como una estructura de datos personalizada, como una List de beans que contienen los datos de cada fila, pero el objeto Result an es un buen candidato para prototipos y pequeas aplicaciones.