07 noviembre, 2006

JSP - Generación de Páginas Dinámicas

Las páginas JSP son páginas HTML que se procesan dentro del web-container antes de ser enviadas al cliente que las requiere.

Para comenzar vemos que en un JSP podemos escribir scripts en Java. Se los llama scriptles y se escriben dentro de <% ... %>.

Para comenzar... nada mejor que analizar un holaMundo.jsp.



Dentro de un scriptlet podemos utilizar ciertos objetos que están definidos implicitamente como por ejemplo el objeto out.
Las JSP deben estar dentro del directorio de la aplicación web o en subdirectorios de este. En nuestro caso deben estar en el directorio hmapp.

Veamos otro ejemplo.



Pero podemos separar el código Java del código HTML simplemente abriendo y cerrando los scriptlets convenientemente.

Si estando en html necesitamos mostrar el valor de una variable Java podemos utilizar una expresión <%=...%>.



Vemos como abrimos y cerramos los scriptles para pasar de Java a HTML y de HTML a Java. Para mostrar el valor de la variable i (estando en HTML) utilizamos la expresión <%=i%>.

Podemos resumir los conocimientos sobre JSP aprendidos hasta aquí con las siguientes tablas.




Parámetros

Las páginas JSP pueden recibir parámetros. Los parámetros siempre son valores String y son pasados a la página por nombre.

Veamos el ejemplo de los números parametrizando la cantidad de números a mostrar.



Al invocar esta página debemos indicar el nombre de parámetro y su valor en el URL así:
http://localhost:8080/hmapp/numeros.jsp?n=20

Vemos que luego del recurso (en este caso la página numeros.jsp), los parámetros se indican despues del caracter “?”. El formato es: nomParam=Valor y si hubiera varios parámetros se los separa con “&”.

Modificaremos el ejemplo anterior para indicar desde y hasta que números mostrar en la página.



Ahora debemos pasarle dos parámetros al momento de invocar la página JSP:

http://localhost:8080/SZ_ZWEB0/numeros.jsp?desde=20&hasta=40


Actualicemos la tabla de resumen de objetos implícitos y elementos de JSP:




Formularios

Para mejorar la aplicación anterior podemos desarrollar una página inicial que tenga un formulario con dos campos: desde y hasta de forma tal que el submit del formulario envie los valores tipeados en los campos como parámetros a la página numeros.jsp.



Cuando presionemos el botón “Enviar” la página invocará a numeros.jsp
(form action=“numeros.jsp”) pasándole como parámetro los valores que contengan los controles (input type =“text”) desde y hasta. Justamente el atributo name del control indica que nombre de parámetro se utilizará para enviar el valor.

El resultado es:




Incluir Páginas

JSP permite construir páginas complejas a partir de la inclusión de otras más pequeñas y simples de resolver. Esto es una opción fundamental para desarrollar páginas.

Modificaremos la aplicación anterior para que se vea así:



Debemos modificar la página index.jsp para que incluya a la página numeros.jsp. Para esto utilizaremos la sentencia .



La salida de la página incluida (numeros.jsp) aparecerá exactamente donde esté la sentencia .

Veamos la página numeros.jsp modificada para ser incluida en la página principal.



Notemos que ahora la página numeros.jsp no tiene los tags html y body. Esto es porque está incluida dentro de otra página que (probablemente) ya tendrá estos tags.


La Sesión Web

La sesión es el recurso que tenemos (como programadores web) para identificar a un cliente dentro de nuestra aplicación.

Por cada cliente (usuario) que accede a nuestra aplicación web el container le asigna un sessionId único para toda la corrida de la aplicación.

Recordemos que HTTP funciona en modo request/response. Esto significa que el cliente (navegador) envia un request (pidiendo una página jsp) y el container le envia como respuesta un response.



Lo anterior implica que la única comunicación que existe entre el navegador y el server es el request/response. No vuelve a haber otra comunicación hasta el próximo request y su correspondiente response.

La sesión nos permite contener los objetos relacionados a cada usuario de la aplicación.

Veamos un ejemplo:



En esta página basicamente seteamos en la sesión (como atributo) un objeto Date inicializado con la fecha y hora actual.

El if( d==null ) es para verificar que el objeto sea seteado solo la primera vez que el usuario ingresa a la página (esto es obsoleto, luego lo reemplazaremos por un session listener).

En la otraPagina.jsp simplemente tomamos de la sesión el atributo “fechahora” y lo mostramos.



Notemos que para desarrollar este ejemplo utilizamos el objeto implícito session y un nuevo elemento de JSP: una directiva <%@ ... %>. Con las directivas podemos (entre otras cosas) importar paquetes Java.

Actualicemos la tabla de resumen:




Session Listener

El manejo que hicimos en el ejemplo anterior (controlar “la primera vez” con un if) no es el más prolijo ni tampoco el más seguro.

Que pasa si por algún motivo el usuario accede directamente a la segunda página? La salida será: “Yo recuerdo que usted llego a las: null”.

J2ee permite definir listeners “clases que escuchan”. En particular los session listeners son clases que escuchan eventos web.

Los session listeners son clases java que implementan la interface HttpSessionListener y están registradas (como listeners) en el web.xml de la aplicación web. Luego el container los notifica cada vez que se crea una sesión y cada vez que se destruye.

Implementaremos el ejemplo anterior utilizando el session listener EscuchaSession.java


Paso 1 (de 3): Escribir la clase EscuchaSession.java que implementa HttpSessionListener.



Paso 2 (de 3): Modificar el archivo web.xml para registrar la clase como listener.



Paso 3 (de 3): Modificar la página index.jsp. Simplemente podemos tomar de la sesión el objeto fechahora y utilizarlo.



Antes de que el usuario acceda a cualquier página el container invocará al método sessionCreated() del listener EscuchaSession.

Entonces en nuestra página simplemente tomamos el objeto fechahora de la sesión y lo utilizamos. No necesitamos verificar si existe o no porque estamos seguros de que existe.

El container nos garantiza que cada vez que se cree una sesión, primero se notificará al listener.


Implementando un Changuito de Compras

Desarrollaremos la siguiente aplicación.



La funcionalidad de esta aplicación es simple. El usuario ingresa un ítem y presiona el botón “Agregar”. Luego el ítem se incorpora a la lista. Los ítems pueden eliminarse clickeando en el link [Borrar].


Análisis

Tendremos dos páginas: index.jsp y listaItems.jsp. La primera tendrá el formulario (para que el usuario tipee el ítem) e incluirá a la segunda.

Los items que vaya acumulando cada usuario los mantendremos en un Vector en la sesión.

Para simplificar el desarrollo y hacer el código más simple y claro introduciremos el concepto de páginas de presentación y páginas de proceso. Veamos el gráfico:



Vemos que el action del formulario envia la información a una página que llamaremos agregaItemPRO.jsp. Esta página recibe el ítem como parámetro y debe agregarlo al vector de ítems que está publicado en la sesión. Luego “forwardea” a la página principal (index.jsp).

La página listaItems.jsp toma el vector de la sesión, lo itera y muestra la lista de ítems.

Por último, los links deben enviar como parámetro (a la página borraItemPRO.jsp) la posición del ítem a borrar. Esta página recibe ese valor, toma el vector de la sesión y le elimina el elemento en la posición indicada. Luego forwardea a la página principal.

Las páginas agregaItemPRO.jsp y borraItemPRO.jsp son páginas de proceso porque simplemente procesan los datos y luego forwardean a la página de presentación (en este caso: index.jsp).

Las páginas de proceso solo tienen código Java. Más adelante veremos como aplicando el patrón de diseño MVC (Model View Controller) estas páginas serán reemplazadas por clases Java.











Debemos agregar a la tabla de elementos JSP el objeto implícito pageContext.




Ciclo de Vida de las Páginas JSP

Las páginas JSP son servlets. El container convierte el código JSP en un código Java correspondiente a un servlet equivalente, lo compila y lo instancia. Este proceso lo realiza cada vez que se verifique que la fecha/hora del .class sea menor que la fecha/hora del .JSP.

Una vez que el servlet está generado entonces responde al ciclo de vida de los servlets.

Los servlets se instancian y la instancia permanece activa hasta que el container decida bajarla.

Una misma instancia es capáz de atender varios requerimientos. Esto hace que las variables de instancia tengan un efecto de “persistencia”. Sin embargo, esta misma característica hace que las variables de instancia sean variables compartidas entre los diferentes usuarios que acceden al servlet (o JSP que es lo mismo).

El siguiente gráfico explica lo anterior.



Vemos que una misma instancia del servlet atiende más de un request aún si los request provienen de diferentes usuarios (sesiones, host, etc).


Declaraciones <%! ... %>

Con las declaraciones podemos definir variables de instancia y métodos en las páginas JSP.



Ahora podemos probar de acceder a esta página desde diferentes navegadores y veremos como se incrementa el contador.

El siguiente ejemplo muestra como podemos utilizar las expresiones para definir métodos.



Obviamente no es la idea programar métodos en las páginas JSP, pero a veces ayudan a procesar Strings, fechas, etc.