Вы находитесь на странице: 1из 166

Módulo 5

Desarrollo de
componentes web
con tecnologías
Servlet y JSP

Profesional en
Plataforma

JAVA
www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Contenido
Introducción y Objetivos ........................................................................................................ 1
Unidad 1. Introducción a las Tecnologías de las Aplicaciones WEB ............................................... 2
Definir la tecnología servlet .................................................................................................................................... 3
Definir la tecnología JavaServer Pages ................................................................................................................... 4
JSTL ......................................................................................................................................................................... 5
Definir la tecnología EJB ......................................................................................................................................... 5
Definir la tecnología Struts ..................................................................................................................................... 6
Definir la tecnología JavaServer Faces .................................................................................................................... 7
Definir la tecnología Java Message Service ............................................................................................................ 8
Definir la tecnología JDBC....................................................................................................................................... 9
Laboratorio: Creación de proyecto Web. ............................................................................................................... 9
Unidad 2. Desarrollo de un Componente Vista ......................................................................... 12
Métodos más importantes de la clase HttpServlet. .............................................................................................. 13
Métodos de la clase ServletRequest ..................................................................................................................... 14
Métodos de la clase ServletResponse .................................................................................................................. 15
Buffering............................................................................................................................................................... 15
Método Service .................................................................................................................................................... 15
Cabeceras ............................................................................................................................................................. 16
Elementos del path de la petición ........................................................................................................................ 16
Desarrollar un servlet HTTP sencillo ..................................................................................................................... 17
Configuración de un servlet .................................................................................................................................. 18
Laboratorio: Solicitud de un Servlet. .................................................................................................................... 19
Unidad 3. Desarrollo de un componente controlador ................................................................ 21
Desarrollar un Servlet con getParameterValues ................................................................................................... 26
Laboratorio: Recogida de parámetros .................................................................................................................. 28
Unidad 4. Desarrollo de Formularios Dinámicos ....................................................................... 30
Introducción ciclo de vida de un Servlet ............................................................................................................... 30
Parámetros de inicialización de un Servlet ........................................................................................................... 31
Controladores de error ......................................................................................................................................... 33
Seguridad ............................................................................................................................................................. 34
Laboratorio: Ciclo de vida de un servlet ............................................................................................................... 37
Unidad 5 . Uso compartido de recursos de la aplicación con el contexto servlet ........................... 41

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Describir la finalidad y las funciones del contexto servlet. ................................................................................... 41
Interface ServletContext....................................................................................................................................... 44
Eventos ServletContext ........................................................................................................................................ 47
Interface ServletContextListener .......................................................................................................................... 47
Unidad 6 . Diseño de la Capa de Negocio ................................................................................ 48
Arquitectura Aplicaciones J2EE ............................................................................................................................ 50
Las etapas del análisis y del diseño orientado a objetos ...................................................................................... 50
Modelo Tres Capas ............................................................................................................................................... 52
Modelo Cuatro capas ........................................................................................................................................... 54
Diseño de componentes ....................................................................................................................................... 54
Unidad 7. Desarrollo de Aplicaciones Eeb con Struts ................................................................ 56
Marco de trabajo MVC ......................................................................................................................................... 57
Desarrollar una clase action de Struts .................................................................................................................. 58
Fichero de Configuración de los Mapeos de Action ............................................................................................. 60
Laboratorio: Creación de propiedades en el archivo ApplicationResource. ......................................................... 65
Unidad 8. Desarrollo de Aplicaciones Web con Administración de Sesiones ................................. 67
Desarrollar servlets utilizando la administración de sesiones .............................................................................. 69
Describir la implementación de cookies de la administración de sesiones. ......................................................... 72
Ejemplo de uso de cookies ................................................................................................................................... 72
Laboratorio: Creación y uso de Cookies. .............................................................................................................. 75
Unidad 9. Uso de Filtros en Aplicaciones Web .......................................................................... 78
Programando los filtros ........................................................................................................................................ 79
Configurar un filtro en el archivo web.xml ........................................................................................................... 82
Unidad 10. Integración de Aplicaciones Web con Bases de Datos ............................................... 85
Tipos de drivers .................................................................................................................................................... 85
Diseñar una aplicación web para integrarla con un DBMS ................................................................................... 86
Conexión .............................................................................................................................................................. 86
Creando sentencias SQL ....................................................................................................................................... 87
API de Java Naming and Directory Interface (JNDI) .............................................................................................. 96
Los servicios de Nombre y Directorio ................................................................................................................... 97
Interacción con los servicios de Nombre y Directorio .......................................................................................... 97
Proveedores de servicios JNDI .............................................................................................................................. 98
Laboratorio: Paginación de registros. ................................................................................................................... 98
Unidad 11. Desarrollo de páginas JSP ................................................................................... 104
Introducción a la tecnología de páginas JSP ....................................................................................................... 104

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Elementos de Script JSP ...................................................................................................................................... 105
Directiva JSP page ............................................................................................................................................. 107
Acciones ............................................................................................................................................................. 108
Laboratorio: Directivas JSP ................................................................................................................................. 115
Unidad 12. Desarrollo de páginas JSP con etiquetas personalizadas .......................................... 121
Diseñar una aplicación web con etiquetas personalizadas ................................................................................. 121
Etiquetas con contenido en el cuerpo ................................................................................................................ 126
Utilizar etiquetas JSTL en una página JSP ........................................................................................................... 127
Base de Datos ..................................................................................................................................................... 132
Laboratorio: Contador de visitas con Custom Tags. ........................................................................................... 141
Contador.tld ....................................................................................................................................................... 141
Web.xml ............................................................................................................................................................. 141
Contador.java ..................................................................................................................................................... 142
indice.jsp ............................................................................................................................................................ 143
Unidad 13. Desarrollo de Aplicaciones Web con la Clase ActionForm de Struts............................ 144
Crear una clase ActionForm ............................................................................................................................... 145
Laboratorio: Internacionalizar una aplicación .................................................................................................... 150
Unidad 14. Construcción de Componentes de Presentación Web Reutilizables ............................ 152
Crear diseños utilizando la infraestructura Struts Tiles ...................................................................................... 155
Ejemplo de uso de plantillas ............................................................................................................................... 157
Laboratorio: Librería de etiquetas Logic. ............................................................................................................ 160
IndexLibros.jsp ................................................................................................................................................... 160
Libros.java .......................................................................................................................................................... 161

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Introducción y Objetivos
1

Introducción y Objetivos
Durante el desarrollo de este módulo el estudiante entenderá los conceptos básicos de las
aplicaciones en capas para lograr crear una aplicación. También se darán los conocimientos que le
permitan desplegar y ejecutar una aplicación en un servidor JAVA EE.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 1. Introducción a las Tecnologías de
las Aplicaciones WEB
Objetivos
 Entender los conceptos básicos de las aplicaciones en capas.
 Entender los conceptos básicos de la Plataforma Java EE.
 Crear una aplicación Java EE multicapa.
 Desplegar y ejecutar la aplicación en un servidor Java EE.
 Saber dónde buscar más información acerca de la plataforma Java EE.

Introducción
La plataforma Java, Enterprise Edition 5 (Java EE 5), es una plataforma de programación para
desarrollar y ejecutar software de aplicaciones en Lenguaje de programación Java con arquitectura
de N capas distribuidas y que se apoya ampliamente en componentes de software modulares
ejecutándose sobre un servidor de aplicaciones.

Las características más importantes de esta plataforma son:


Heterogénea: Debe permitir múltiples plataformas, sistemas operatives y lenguajes de desarrollo.
Fiable: Tiene que dar la confianza de que cumplirá su cometido.
Segura: Debe controlar el acceso, la autorización y el transporte
Robusta: Debe ser tolerante a fallos.
Escalable: Tiene que facilitar la ampliación y modificación necesarias
Alta disponibilidad: Debe ser fácil su adquisición, formación y actualización.
Fácil mantenimiento: Debe ser fácil mantener el sistema mediante la actualización de sus
componentes.
SUN libera en el Java EE:
Especificaciones de cada tecnología incluida.
Test de compatibilidad (Compatibility Test Suite)
Implementación de referencia. Para desarrollo de aplicaciones, pero de uso
no libre. (Sun Java System Application Server Platform Edition ..)
Las tecnologías que incluye Java EE 5 son las siguientes:
Enterprise JavaBeans (EJB).
Servlet
JavaServer Page (JSP)
JavaServer Pages Standard Tag Library (JSTL).

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
JavaServer Faces
Java Message Service (JMS).
Java Transaction API (JTA).
JavaMail API y JavaBeans Activation Framework (JAF).
Tecnologías XML (JAXP, JAX-RPC, JAX-WS, JAXB, SAAJ, JAXR)
JDBC API
Java Naming and Directory Interface (JNDI)
Java Authentication and Authorization Service (JAAS)

Definir la tecnología servlet


Los servlets (al igual que los applet) se ejecutan en una caja restringida (sandbox) lo que protege al
servidor de cualquier mal funcionamiento del servlet. Esto permite a los proveedores de Internet
que sus clientes depositen servlets sin temor de que sean maliciosos. Se incrementa la seguridad
respecto a cualquier otra tecnología notablemente.
Al estar escritos en Java, tienen todas las ventajas de este lenguaje (pueden hacer uso de cualquier
paquete de Java). Como es un lenguaje altamente escalable surgirán paquetes de una forma muy
rápida.
Los servlets son portables entre plataformas ("escribir una vez, ejecutar en cualquier lugar"). Los
servidores Web más populares, dicen soportar los servlets.
Los servlets son componentes de la parte del servidor de Java EE, encargados de generar
respuestas a las peticiones recibidas de los clientes.
En la mayoría de las páginas Web se van a introducir los llamados formularios, los cuales sirven para
recoger datos aportados por los clientes. Estos formularios van a ser una mezcla de código HTML y
de Scripts  Son programas que se ejecutan en el servidor y su función fundamental es la de
recoger los datos que el cliente ha introducido a través de un formulario y, en base a ellos,
construir una página dinámicamente para responder a la petición. Estas páginas se llaman dinámicas
porque no van a existir en el disco duro del servidor sino que se van a generar como respuesta a
una petición hecha desde el cliente a través de un formulario.
Estos Scripts aún se usan mucho por varios motivos:
Se van a encontrar en el servidor por lo que son totalmente independientes del navegador que use
el cliente.
La respuesta que generar va a ser mucho más rápida debido a su ubicación en el servidor.
La seguridad aumenta mucho debido a que los programas van a correr bajo el control directo del
administrador del servidor.
Los Scripts más extendidos son los denominados CGI (Common Gateway Interface). Estos CGI
tienen una gran desventaja: son poco eficientes debido a que el servidor ejecuta una copia de los
mismos por cada petición que le llega. Así, si el sitio Web es bastante popular, supone una pérdida
considerable de rendimiento. Para solventar este problema, los fabricantes han desarrollado
alternativas: Microsoft  ISAPI; NetScape  NSAPI; JavaSoft  Servlets.
Las ventajas de los Servlets en comparación con las CGI son:
Los Servlets no se van a ejecutar en un proceso separado, por lo que no necesita ejecutarse cada
vez que recibe una petición.
Una vez que se ha invocado, quedan almacenados en memoria por lo que consumen menos
recursos, aunque se le esté invocando constantemente. Esto significa que una sola instancia de un
Servlet responde a todas las peticiones con lo que, además del ahorro de recursos, se pueden
gestionar, de modo más adecuado, los datos que le llegan.
Los Servlets van a ser aplicaciones que van a ser ejecutados, al igual que los Applets de Java, por
un motor Servlet en una caja restringida (lo que se conoce con el nombre de Sandbox) por lo que se
aumenta la seguridad enormemente. Los proveedores de Internet, debido a este motivo, no van a

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
tener ningún temor a que los usuarios puedan introducir Servlet en el servidor, ya que se
encuentran protegidos frente a código malicioso.
Al estar escritos en Java, tienen todas las ventajas de este lenguaje (pueden hacer uso de cualquier
paquete de Java). Como es un lenguaje altamente escalable surgirán paquetes de una forma muy
rápida (por ejemplo, ya existen paquetes para la gestión de documentos XML).
Los Servlets son portables entre plataformas (siguen la premisa de Java "escribir una vez, ejecutar
en cualquier lugar"). Netscape, Apache e IIS, los tres servidores Web más populares, soportan los
Servlets.
En esta imagen podemos apreciar el esqueleto básico de una aplicación Servlet:

Las sentencias import indican al compilador de Java la inclusión de todas las clases públicas e
interfaces de los paquetes java.io y javax.servlet en la compilación.
La clase extiende (extends), es heredera de la clase HttpServlet. Esta clase proporciona la interfaz
para que el servidor le pase las peticiones al servlet y el mecanismo para controlar el ciclo de vida del
servlet.

Definir la tecnología JavaServer Pages


Las JavaServer Pages (JSP) permiten separar la parte dinámica de tus páginas de la parte HTML
estática. Para ello, basta con:
 Escribir la parte estática HTML de la manera habitual.
 Encerrar el código Java que genera la parte dinámica de la página entre unos delimitadores
especiales, la mayoría de los cuales empiezan por
 Si quieres tener en la salida estática HTML el conjunto de caracteres

En esta imagen podemos apreciar las directivas que utilizaremos en aplicaciones JSP:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Una página JSP cuando se ejecuta el servidor de base de datos genera un servlet. El ejemplo
anterior generará un servlet como el de la imagen siguiente:

El motor de las páginas JSP está basado en los servlets de Java -programas en Java destinados a
ejecutarse en el servidor-, aunque el número de desarrolladores que pueden afrontar la
programación de JSP es mucho mayor, dado que resulta mucho más sencillo aprender que los
servlets.

En JSP creamos páginas de manera parecida a como se crean en ASP o PHP -otras dos tecnologías
de servidor-. Generamos archivos con extensión .jsp que incluyen, dentro de la estructura de
etiquetas HTML, las sentencias Java a ejecutar en el servidor. Antes de que sean funcionales los
archivos, el motor JSP lleva a cabo una fase de traducción de esa página en un servlet,
implementado en un archivo class (Byte codes de Java). Esta fase de traducción se lleva a cabo
habitualmente cuando se recibe la primera solicitud de la página .jsp, aunque existe la opción de
precompilar en código para evitar ese tiempo de espera la primera vez que un cliente solicita la
página.

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.

Definir la tecnología EJB


Un EJB (Enterprise JavaBean) es un objeto seguro, transaccional y quizás persistente, pueden ser
remoto o local, oculta las APIs de seguridad, transacciones y persistencia ,usa IIOP e
interoperabilidad con CORBA.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Un ejemplom práctico sería el siguiente:
 Customer.java: es en este ejemplo el "remote interface" que define los métodos de negocio
que puede invocar el cliente. En este caso podéis comprobar que existen sólo un método
getInformation, que permite obtener la información asociada a un usuario de la tienda de
venta de Logos. Este método se implementa en la clase del bean.
 CustomerHome.java: es en este ejemplo el "home interface" que define los métodos que le
permiten al cliente crear, buscar y eliminar el bean. En este caso podéis comprobar que esta
interfaz proporciona un método que permite crear el bean a partir de los datos asociados a
un usuario, devolviendo un objeto que implementa la interfaz remota definida en
Customer.java, de esta forma se crea un nuevo usuario en nuestro sistema que se
almacenará de manera persistente en la base de datos. En esta interfaz también existe un
método que permite buscar una instancia del bean a partir de la clave primaria, que en este
caso es el nombre del usuario.
 CustomerBean.java: es en este ejemplo el código del "enterprise bean" que implementa los
métodos de negocio definidos en el interfaz remoto Customer, además de todos los métodos
definidos en la interfaz EntityBean.
 CustomerTO.java: es una clase auxiliar que representa la información asociada a un usuario,
es una clase serializable ya que el método de negocio definido en la interfaz remota devuelve
un objeto de este tipo.

Definir la tecnología Struts


Struts inicialmente pertenecía al proyecto Jakarta de la fundación Apache, pero se independizó y
pasó a conocerse como Apache Struts. Básicamente, se presenta como un framework de soporte de
desarrollo de aplicaciones web siguiendo el conocido patrón MVC (Modelo-Vista-Controlador)
corriendo bajo J2EE. Este patrón arquitectónico separa los datos de una aplicación software, su
interfaz de usuario y la lógica de cada uno de las entidades conceptuales que la forman, en tres
componentes distintos y es muy extendido y recomendable su uso en el desarrollo de aplicaciones
web, siendo uno de los más fuertes pilares sobre los que se sustentan actualmente las buenas
prácticas de diseño de aplicaciones software para la web donde la vista se centra al HTML de la
página contenedora del servicio.
Bajo esta idea, Struts se presenta como un enorme aliado a la hora de construir aplicaciones web de
una forma elegante y con un diseño basado en una de las corrientes más influyentes dentro de las
buenas prácticas del desarrollo web.
El desarrollo de una aplicación web mediante Struts se puede subdividir en varias tareas, en primer
lugar tendremos que definir la lógica de control de una entidad, persistente o no, que necesitemos
para implementar la funcionalidad del servicio o aplicación que estemos desarrollando. Por ejemplo,
supongamos que deseamos desarrollar un sistema de e-venta de entradas o tickets para
determinados eventos culturales. Después de un proceso de elicitación y análisis del software
podremos ser capaces de identificar que necesitamos una serie de objetos o entidades en nuestra
aplicación capaces de representar los conceptos que manejamos en ese dominio, como pueden ser
una entrada, un evento o el mismo usuario de la web que actuará de comprador, y que estos a su
vez, deberán almacenar la información necesaria para representar eficazmente a cada uno de ellos.
Una vez implementados estos elementos como clases Java con sus correspondientes constructores,
y métodos de acceso y consulta a los atributos de estas, los conocidos como getters y setters,
necesitaremos mantener una relación con la base de datos que soportará el almacenamiento de
cada uno de los registros que se adecuen a esas entidades persistentes. Por lo que generaremos, si
es necesario, las correspondientes clases para tal fin, una buena práctica es hacer uso de patrones
DAO. El cómo la arquitectura apunta a un determinado JDBC para acceder a una base de datos se
lleva a cabo mediante la configuración de un simple fichero de properties.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Definir la tecnología JavaServer Faces
JavaServer Faces (JSF) es una tecnología y framework para aplicaciones Java basadas en web que
simplifica el desarrollo de interfaces de usuario en aplicaciones Java EE. JSF usa JavaServer Pages
(JSP) como la tecnología que permite hacer el despliegue de las páginas, pero también se puede
acomodar a otras tecnologías como XUL.
JSF incluye:
Un conjunto de APIs para representar componentes de una interfaz de usuario y administrar su
estado, manejar eventos, validar entrada, definir un esquema de navegación de las páginas y dar
soporte para internacionalización y accesibilidad.
Un conjunto por defecto de componentes para la interfaz de usuario.
Dos bibliotecas de etiquetas personalizadas para JavaServer Pages que permiten expresar una
interfaz JavaServer Faces dentro de una página JSP.
- Un modelo de eventos en el lado del servidor.
- Administración de estados.
- Beans administrados.
El objetivo de la tecnología JavaServer Faces es desarrollar aplicaciones web de forma parecida a
como se construyen aplicaciones locales con Java Swing, AWT (Abstract Window Toolkit), SWT
(Standard Widget Toolkit) o cualquier otra API similar.
Tradicionalmente, las aplicaciones web se han codificado mediante páginas JSP (JavaServer Pages)
que recibían peticiones a través de formularios y construían como respuesta páginas HTML (Hiper
Text Markup Language) mediante ejecución directa o indirecta -a través
de bibliotecas de etiquetas- de código Java, lo que permitía, por ejemplo, acceder a bases de datos
para obtener los resultados a mostrar amén de realizar operaciones marginales como insertar o
modificar registros en tablas relacionales, actualizar un carrito de la compra, etc.
JavaServer Faces pretende facilitar la construcción de estas aplicaciones proporcionando un entorno
de trabajo (framework) vía web que gestiona las acciones producidas por el usuario en su página
HTML y las traduce a eventos que son enviados al servidor con el objetivo de
regenerar la página original y reflejar los cambios pertinentes provocados por dichas acciones.
En definitivas cuentas, se trata de hacer aplicaciones Java en las que el cliente no es una ventana de
la clase JFrame o similar, sino una página HTML.
Como el lector puede imaginar, cualquier evento realizado sobre una página JSF incurre en una
carga sobre la red, ya que el evento debe enviarse a través de ésta al servidor, y la respuesta de
éste debe devolverse al cliente; por ello, el diseño de aplicaciones JavaServer Faces
debe hacerse con cuidado cuando se pretenda poner las aplicaciones a disposición del mundo entero
a través de internet. Aquellas aplicaciones que vayan a ser utilizadas en una intranet podrán
aprovecharse de un mayor ancho de banda y producirán una respuesta mucho más rápida.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Una de las ventajas de que JSF sea una especificación estándar es que pueden encontrarse
implementaciones de distintos fabricantes. Esto permite no vincularse exclusivamente con un
proveedor concreto, y poder seleccionar el que más interese en cada caso según el número de
componentes que suministra, el rendimiento de éstos, soporte
proporcionado, precio, política de evolución, etc.
JSF trata la vista (la interfaz de usuario) de una forma algo diferente a lo que estamos
acostumbrados en aplicaciones web, ya que este tratamiento es mucho más cercano al estilo de
Java Swing, Visual Basic o Delphi, donde la programación de la interfaz se hace a través de
componentes y está basada en eventos (pulsación de un botón, cambio en el valor de un campo,
etc.).
JSF es muy flexible. Por ejemplo nos permite crear nuestros propios componentes, y/o crear
nuestros propios renderizadores para pintar los componentes en la forma que más nos convenga.
Una de las grandes ventajas de la tecnología JavaServer Faces es que ofrece una clara separación
entre el comportamiento y la presentación. Las aplicaciones web construidas con tecnología JSP
conseguían parcialmente esta separación. Sin embargo, una aplicación JSP no puede mapear
peticiones HTTP al manejo de eventos específicos de los componentes o manejar elementos UI como
objetos con estado en el servidor. La tecnología JavaServer Faces permite construir aplicaciones web
que introducen realmente una separación entre el comportamiento y la presentación, separación
sólo ofrecida tradicionalmente por arquitecturas UI del lado del cliente.
Separar la lógica de negocio de la presentación también permite que cada miembro del equipo de
desarrollo de la aplicación web se centre en su parte asignada del proceso diseño, y proporciona un
modelo sencillo de programación para enlazar todas las piezas. Por ejemplo,
personas sin experiencia en programación pueden construir páginas JSF usando las etiquetas de
componentes UI que esta tecnología ofrece, y luego enlazarlas con código de la aplicación sin
escribir ningún script ni nada.
Otro objetivo importante de la tecnología JavaServer Faces es mejorar los conceptos familiares de
componente-UI y capa-web sin limitarnos a una tecnología de script particular o un lenguaje de
marcas. Aunque la tecnología JavaServer Faces incluye una librería de etiquetas JSP personalizadas
para representar componentes en una página JSP, las APIs de JavaServer Faces se han creado
directamente sobre el API JavaServlet. Esto nos permite, teóricamente, hacer algunas cosas
avanzadas: usar otra tecnología de presentación junto a JSP, crear nuestros propios componentes
personalizados directamente desde las clases de componentes, y generar salida para diferentes
dispositivos cliente, entre otras.
En definitivas cuentas, la tecnología JavaServer Faces proporciona una rica arquitectura para
manejar el estado de los componentes, procesar los datos, validar la entrada del usuario, y manejar
eventos.

Definir la tecnología Java Message Service


La API Java Message Service (en español servicio de mensajes Java), también conocida por sus
siglas JMS, es la solución creada por Sun Microsystems para el uso de colas de mensajes. Este es un
estándar de mensajería que permite a los componentes de aplicaciones basados en la plataforma
Java2 crear, enviar, recibir y leer mensajes. También hace posible la comunicación confiable de
manera síncrona y asíncrona.
El servicio de mensajería instantánea también es conocido como Middleware Orientado a Mensajes
(MOM por sus siglas en inglés) y es una herramienta universalmente reconocida para la construcción
de aplicaciones empresariales.
Dicha API es parte integral de la versión 2 de Java.
Existen dos modelos de la API JMS, los cuales son:
 Modelo Punto a Punto (point to point): Este modelo cuenta con solo dos clientes, uno que
envía el mensaje y otro que lo recibe. Este modelo asegura la llegada del mensaje ya que si

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
el receptor no esta disponible para aceptar el mensaje o atenderlo, de cualquier forma se le
envía el mensaje y este se encola en una pila del tipo FIFO para luego ser recibido según
haya entrado.
 Modelo Publicador/Suscriptor (Publish/Subscribe): Este modelo cuenta con varios clientes,
unos que publican temas(tópicos) o eventos, y los que ven estos tópicos, a diferencia del
modelo punto a punto este modelo tiende a tener más de un consumidor.
Ambos modelos pueden ser síncronos mediante el método receive y asíncronos por medio de un
MessageListener.

Definir la tecnología JDBC


Java Database Connectivity, más conocida por sus siglas JDBC, es una API que permite la ejecución
de operaciones sobre bases de datos desde el lenguaje de programación Java, independientemente
del sistema operativo donde se ejecute o de la base de datos a la cual se accede, utilizando el
dialecto SQL del modelo de base de datos que se utilice.
El API JDBC se presenta como una colección de interfaces Java y métodos de gestión de
manejadores de conexión hacia cada modelo específico de base de datos. Un manejador de
conexiones hacia un modelo de base de datos en particular es un conjunto de clases que
implementan las interfaces Java y que utilizan los métodos de registro para declarar los tipos de
localizadores a base de datos (URL) que pueden manejar. Para utilizar una base de datos particular,
el usuario ejecuta su programa junto con la biblioteca de conexión apropiada al modelo de su base
de datos, y accede a ella estableciendo una conexión, para ello provee el localizador a la base de
datos y los parámetros de conexión específicos. A partir de allí puede realizar con cualquier tipo de
tareas con la base de datos a las que tenga permiso: consulta, actualización, creación, modificación
y borrado de tablas, ejecución de procedimientos almacenados en la base de datos, etc.

Ver Video: Proyecto Servlety JSP, en la Unidad 1,


en el Módulo 5, en la plataforma elearning

Laboratorio: Creación de proyecto Web.

Objetivo

Crear un proyecto web con NetBeans

Enunciado:
Abrir NetBeans y crear un proyecto web siguiendo los siguientes pasos:
1. Seleccionar la opción archivo y nuevo proyecto.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
2. En categorías elegimos Java Web, y en proyectos web application.

3. Llamaremos al proyecto Laboratorio1 y lo guardamos en nuestra carpeta de trabajo.

4. Seleccionamos el servidor Apache Tomcat.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
5. Por último, no seleccionaremos ningún Framework y pulsamos en finalizar.

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 2. Desarrollo de un Componente
Vista
Objetivos
 Entender el papel que juega el componente vista en un desarrollo web.
 Trabajar con la configuración de un servlet.

Introducción HttpServlet
Es una clase que implementa la interfaz Servlet incorporando además métodos específicos para
servidores Web.
Un uso típico de HttpServlet es el procesamiento de formularios html.
El método service() de la clase HttpServlet lanza diferentes métodos dependiendo de las diferentes
peticiones que se pueden recibir y que ya explicamos al analizar el protocolo HTTP. Este método es
capaz de reconocer las peticiones estándar del protocolo HTTP 1.1 y no es conveniente
sobreescribirlo en las subclases, a no ser que se desee una implemetación más específica de él.

Los tipos de petición que reconoce y el método al que llama se encuentran en la siguiente tabla:
Tipo de petición Método al que se llama.
GET doGet(HttpServletRequest, HttpServletResponse)
POST doPost(HttpServletRequest, HttpServletResponse)
HEAD Devuelve lo mismo que GET pero sin el cuerpo.
PUT doPut(HttpServletRequest, HttpServletResponse)
DELETE doDelete(HttpServletRequest,
HttpServletResponse)
OPTION No está permitido sobrecargarlo.
TRACE No está permitido sobrecargarlo.
Cualquier otro tipo desconocido Devuelve el mensaje de error "BAD REQUEST".

Las implementaciones de estos métodos por defecto devuelven el error "BAD REQUEST", por tanto,
si queremos obtener cierta funcionalidad de ellos debemos sobreescribirlos en nuestro Servlet.
La interface Servlet declara los métodos del ciclo de vida de un servlet, que son:
void init(ServletConfig config): es llamado, una sola vez, por el contenedor del servidor J2EE
compatible donde se hospeda el servlet y se emplea para inicializarlo. Se ejecutará cuando se realice
la primera petición. Este método y el resto del ciclo de vida se tratarán con más detalle en el
siguiente apartado.
void destroy(): es llamado por el contenedor antes de que el servlet se descargue de memoria y
deje de prestar servicio.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
void service(ServletRequest request, ServletResponse reponse): es invocado por el contenedor para
procesar las peticiones, una vez que el servlet se ha inicializado. Sus argumentos son instancias de
las interfaces javax.servlet.ServletRequest y javax.servlet.ServletResponse que modelan,
respectivamente, la petición del cliente y la respuesta del servlet. En un servlet http, este método
suele sustituirse por los métodos de javax.servlet.http.HttpServlet.
void doPost(HttpServletRequest request, HttpServletResponse response) para gestionar peticiones
post.
El método POST solo esta accesible desde los formularios. Se envían los parámetros de forma
implícita junto a la página, es decir, al pasar los parámetros, nosotros no vemos reflejado en ningún
sitio qué parámetros son y cual es su valor.

void doGet(HttpServletRequest request, HttpServletResponse response) para gestionar peticiones


get

El método GET envía los parámetros de forma explicita junto a la página, mostrando en la barra de
navegación los parámetros y sus valores. Son esas largas cadenas que aparecen en algunas páginas
en nuestra barra de navegación.

Métodos más importantes de la clase HttpServlet.


Método Descripción
doDelete(HttpServletRequest req, Recibe una petición HTTP tipo DELETE del método
HttpServletResponse resp) protegido service y gestiona la petición.

doGet(HttpServletRequest req, Recibe una petición HTTP tipo GET del método
HttpServletResponse resp) protegido service y gestiona la petición.

doOptions(HttpServletRequest req, Recibe una petición HTTP tipo OPTIONS del


HttpServletResponse resp) método protegido service y gestiona la petición.

doPost(HttpServletRequest req, Recibe una petición HTTP tipo POST del método
HttpServletResponse resp) protegido service y gestiona la petición.

doPut(HttpServletRequest req, Recibe una petición HTTP tipo PUT del método
HttpServletResponse resp) protegido service y gestiona la petición.

doTrace(HttpServletRequest req, Recibe una petición HTTP tipo TRACE del método
HttpServletResponse resp) protegido service y gestiona la petición.

getLastModified(HttpServletRequest req) Retorna el tiempo en milisegundos desde el 1 de


Enero de 1970.
service(HttpServletRequest req, Recibe peticiones estándar HTTP desde el método
HttpServletResponse resp) público service y los despacha a los métodos
doxxx definidos en esta clase.
service(ServletRequest req, Despacha peticiones del cliente al método
ServletResponse res) protegido service.

Todo los métodos reciben dos parámetros que son HttpServletRequest(Objeto que representa a la petición y
cuyos métodos nos van a permitir analizarla.) y HttpServletResponse (Objeto que nos va a permitir emitir la
respuesta).

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Métodos de la clase ServletRequest
Método Descripción
getAttribute(java.lang.String name) Devuelve el valor del atributo especificado como
un objeto.
getAttributeNames() Devuelve un objeto Enumeration que contiene los
nombres de todos los atributos de la petición que
están disponibles.
getCharacterEncoding() Devuelve el nombre del estilo de codificación de
caracteres usados en esta petición.
getContentLength() Devuelve la longitud, en bytes, del contenido de
la petición o -1 si la longitud no se conoce.
getContentType() Devuelve el tipo MIME del contenido de la petición,
o null si el tipo no es conocido.
getInputStream() Devuelve datos binrarios desde el cuerpo de la
petición como un ServletInputStream, el cual te
da la capacidad de leer toda una línea a la vez.
getParameter(java.lang.String name) Devuelve el valor del parámetro de la petición
especificado como un String o null si el parámetro
no existe.
getParameterNames() Devuelve un objeto Enumeration de objetos String
que contiene el nombre de los parámetros de la
petición.
getParameterValues(java.lang.String nam Devuelve un array de objetos String que contienen
e) todos los valores de los parámetros que tiene la
petición, o null si lo sparámetros no existen.
getProtocol() Devuelve el nombre y versión del protocolo usado
en la petición con el formato:
protocol/majorVersion.minorVersion, por ejemplo,
HTTP/1.1.
getReader() Devuelve el cuerpo de la petición como un
BufferedReader.
getRemoteAddr() Devuelve la dirección IP del cliente que envía la
petición.
getRemoteHost() Devuelve el nombre completo (de la máquina) del
cliente que envía la petición.
getScheme() Devuelve el nombre del esquema usado en la
realización de la petición, por ejemplo, http, https,
or ftp.
getServerName() Devuelve el nombre del host dónde reside es
servidor que recibió la petición.
getServerPort() Devuelve el número el puerto en el cual se recibió
la petición.
setAttribute(java.lang.String key, Almacena un atributo en el contexto de esta
java.lang.Object o) petición.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Métodos de la clase ServletResponse
Método Descripción
getCharacterEncoding() Devuelve el nombre del conjunto de caracteres de
codificación usado para el envío de tipos MIME en el
cuerpo de la respuesta.
getOutputStream() Devuelve un ServletOutputStream adecuado para
escribir datos binarios en la respuesta.
getWriter() Devuelve un objeto PrintWriter que puede ser usado
para enviar caracteres de texto al cliente.
setContentLength(int len) Pone la longitud del contenido que el servidor
devuelve al cliente.
setContentType(java.lang.String type) Pone el tipo de contenido de la respuesta que el
servidor envía al cliente.

Buffering
Un contenedor servlet está permitido, aunque no es necesario, para que la salida del buffer vaya al
cliente por motivos de eficiencia. Los servidores típicos crean un buffer por defecto, pero permiten a
los servlets especificar sus parámetros. Los siguientes métodos de la interfaz ServletResponse
permiten al servlet acceder y establecer la información del buffer:
getBufferSize: devuelve el tamaño del buffer que está siendo usado.
setBufferSize: establece el tamaño del buffer.
isCommitted: devuelve true si el cliente devuelve los bytes de respuesta.
reset: limpia toda la información antes de que la respuesta sea enviada, incluyendo las cabeceras y
los códigos de estado.
resetBuffer: limpia toda la información del buffer, sin incluir las cabeceras y los códigos de estado.
flushBuffer: obliga que el buffer se escriba en el cliente.
Estos métodos son proporcionados por la interfaz ServletResponse para permitir operaciones de
buffer que mejoran el rendimiento del servlet usando un ServletOutputStream o un Writer.
Si la respuesta es enviada y se invoca el reset o el resetBuffer, se lanzará una excepción del tipo
IllegalStateException.
Cuando el buffer está lleno, el contenedor debe volcar inmediatamente el contenido al cliente. Si es
la primera información que se manda al cliente, la respuesta se considera que está enviada
(committed).

Método Service
El método Service es el método principal, llamado cuando el servlet recibe una solicitud de servicio.
Define un paquete de lógica de procesamiento proporcionado por el servlet. En la declaración se
puede notar que el denominado método service toma dos parámetros (Objetos): uno llamado
request del tipo HttpServletRequest y otro por nombre response del tipo HttpServletResponse,
ambos representan el objeto de entrada y salida del Servlet respectivamente.
Lo anterior significa que dentro de estos Objetos reside la información con que será atendida la
solicitud así como la información que será enviada de respuesta, por decirlo de otra manera, son
estos dos objetos con los que juega todo Servlet, y por ende un JSP también.
Ejemplo de Servlet con método Service:
import javax.servlet.*;

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
import javax.servlet.http.*;
public class ServletConService extends HttpServlet
{
public void service(HttpServletRequest request,
HttpServletResponse response)
throws IOException
{
response.setContentType("text/html");

PrintWriter out = response.getWriter();


out.println("<HTML>");
out.println("<BODY>");
out.println("Ejemplo con método Service");
out.println("</BODY>");
out.println("</HTML>");
}
}

Cabeceras
Un servlet puede acceder a las cabeceras de una petición HTTP a través de los siguientes métodos
de la interfaz HttpServletRequest:
 getHeader: devuelve el nombre de la cabecera. Aunque puede haber múltiples cabeceras con
el mismo nombre, este método sólo devuelve el nombre de la primera cabecera de la
petición.
 getHeaders: permite acceder a todos los valores asociados a un nombre de cabecera,
devolviendo una Enumeration de String’s.
 getHeaderNames
 Las cabeceras pueden contener representaciones de enteros (int) o fechas (Date)
almacenadas como String. Para acceder a esta información, la interfaz HttpServletRequest
proporciona métodos para acceder a la información en uno de estos formatos:
 getIntHeader: si no puede transformar el valor de la cabecera a entero, lanzará la excepción
NumberFormatException.
 getDateHeader: si no puede transformar el String a fecha, lanzará IllegalArgumentException.

Elementos del path de la petición


El path de la petición a un servicio servlet, está compuesto de muchas secciones importantes. Los
siguientes elementos son obtenidos del path URI de la petición y mostrados a través del objeto de la
petición:
El Path de contexto: es el prefijo del path - asociado con el ServletContext - del que este servlet
forma parte. Si este es el contexto por defecto en la base del espacio de nombres URL del servidor
web, este path debería ser una cadena vacía. De otra manera, si el contexto no está en la raíz del
espacio de nombres del servidor, el path empieza con una carácter “/”, pero no acaba con un
carácter “/”.
Servlet Path: es la sección del path que se corresponde directamente con el mapeo que activa la
petición. Este path empieza con un carácter “/” excepto en el caso que la petición coincida con el
patrón “/*”, en cuyo caso es la cadena vacía.
PathInfo: es la parte del path de la petición que no es parte del Context Path o el Servlet Path.
Camino Context o el Servlet Path. En el caso de ser nulo (si no hay path extra), o es un cadena con

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
un dirección “/”. Los siguientes métodos existen en la interface HttpServletRequest para acceder a
esta información.
getContextPath
getServletPath
getPathInfo
Es importante hacer notar que, excepto para la codificicación URL, las diferencias entre el URI de
petición y las partes del path hacen que siempre se cumpla la siguiente ecuación:
requestURI = contextPath + servletPath + pathInfo

Desarrollar un servlet HTTP sencillo


Crearemos una página Html sencilla con el código siguiente:
<html>

<head>
<title>PAGINA 1</title>
</head>

<body>
<form name="form1" action= "Servlet1" method="post">
<input type="submit" value="enviar">
</form>

</body>

</html>
Al ejecutar la página html y pulsar sobre el botón de submit solicitaremos el Servlet1.
Crear un servlet con el código siguiente:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Servlet1 extends HttpServlet{

public void doPost(HttpServletRequest request, HttpServletResponse response)throws


IOException,ServletException{

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Respuesta Servlet</title>");
out.println("</head>");
out.println("<body bgcolor='white'>");
out.println("<center><h3>Bienvenido</h3></center>");
out.println("</body>");
out.println("</html>");
}
}
En el servlet hemos sobreescrito el método doPost para responser al cliente con el objeto response
una página HTML con un mensaje de bienvenida.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Configuración de un servlet
El fichero web.xml define las asignaciones entre las rutas de URL y los servlets que controlan las
solicitudes con estas rutas. El servidor web utiliza esta configuración para identificar el servlet que
controla una solicitud concreta y ejecuta el método de clase que corresponde al método de solicitud
(por ejemplo, el método doGet() para solicitudes GET HTTP).
Para asignar una URL a un servlet, declara el servlet con el elemento , a continuación,
define una asignación desde una ruta de URL hasta una declaración de servlet con el elemento

El elemento declara el servlet, incluido un nombre utilizado para hacer referencia al servlet
por parte de otros elementos del archivo, la clase que se va a utilizar para el servlet y los
parámetros de inicialización. Puedes declarar varios servlets con la misma clase y diferentes
parámetros de inicialización. El nombre de cada servlet debe ser único en todo el descriptor de
implementación.
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>paquete1.servlet1</servlet-class>
<init-param>
<param-name>nombre</param-name>
<param-value>pepe</param-value>
</init-param>
<init-param>
<param-name>apellido</param-name>
<param-value>pogre</param-value>
</init-param>
</servlet>

<servlet>
<servlet-name>Servlet2</servlet-name>
<servlet-class>paquete2.servlet2</servlet-class>
<init-param>
<param-name>nombre</param-name>
<param-value>pepe</param-value>
</init-param>
<init-param>
<param-name>apellido</param-name>
<param-value>pogre</param-value>
</init-param>
</servlet>
El elemento especifica un patrón URL y el nombre de un servlet declarado que se
va a utilizar para las solicitudes cuya URL corresponde al patrón. El patrón URL puede utilizar un
asterisco (*) al principio o al final del patrón para indicar cero o más caracteres. (El estándar no
admite comodines en mitad de una cadena y no permite varios comodines en un patrón). El patrón
corresponde a la ruta completa de la URL, empezando con e incluyendo la barra inclinada (/),
seguida del nombre de dominio.
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/s1/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>Servlet2</servlet-name>
<url-pattern>/s2/*</url-pattern>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</servlet-mapping>
Ver Video: Primer ejemplo de Servlet, en la Unidad 2,
en el Módulo 5, en la plataforma elearning

Laboratorio: Solicitud de un Servlet.


Objetivos
Desarrollar un ejemplo básico con las clases y métodos principales para la implementación de un
Servlet.
Enunciado
Realizar un Sevlet que nos cree un fichero de texto en el servidor que vaya almacenando un
contador de visitas.
Cada vez que solicitemos el servlet, abrirá el fichero y aumentará el contador.
Cada vez que se aumente el contador, guardaremos la información en el fichero de texto.

import java.io.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletContador extends HttpServlet{

static DataOutputStream escribir;


static DataInputStream leer;
static File archivo;
static int contador;

//------------------------------------------
public void doGet (HttpServletRequest peticion, HttpServletResponse respuesta) throws
IOException, ServletException{
Gestionar(peticion, respuesta);
}
//------------------------------------------
public void doPost (HttpServletRequest peticion, HttpServletResponse respuesta) throws
IOException, ServletException{
Gestionar(peticion, respuesta);
}

//------------------------------------------
public void Gestionar (HttpServletRequest peticion, HttpServletResponse respuesta) throws
IOException, ServletException{

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
archivo = new File ("C:\\EJFundamentos\\Visitas.txt");
DecimalFormat formato = new DecimalFormat("00000");
//para dar formato decimal

if(!archivo.exists()){
escribir= new DataOutputStream (new
FileOutputStream("C:\\EJFundamentos\\Visitas.txt"));
try{
escribir.writeInt(0);
escribir.close();
}catch (IOException e){}
}else{
leer = new DataInputStream (new FileInputStream (archivo));
try{
contador= leer.readInt();
leer.close();
}catch (IOException e){}

}
escribir = new DataOutputStream (new
FileOutputStream("C:\\EJFundamentos\\Visitas.txt"));
try{
escribir.writeInt(++contador);
escribir.close();
}catch (IOException e){}

ServletOutputStream flujo = respuesta.getOutputStream();


respuesta.setContentType("text/html");

flujo.println("<HTML>");
flujo.println("<HEAD>");
flujo.println("<TITLE>RESPUESTA</TITLE>");
flujo.println("</HEAD>");
flujo.println("<BODY TEXT=#FFFFFF BGCOLOR=#000080 LINK = #FFFFFF ALINKCYAN
VLINKORANGE><CENTER>");
flujo.println("<FONT FACE=ARIAL");
String s_cont= formato.format(contador);
flujo.println("<br><h2>Estado del contador de visitas:<br><br>");
flujo.println("<table border=2 align=center width=5% height=1% cellsapcing=2
border=1 cellpadding=3>");
flujo.println("<tr align=center><td><h2>"+ s_cont+"</h2></td></tr></table>");
flujo.println("</font></center></body>");
flujo.println("</html>");
flujo.close();
}

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 3. Desarrollo de un componente
controlador

Objetivos
 Desarrollar un Servlet con los métodos más interesantes.
 Trabajar con el componente controlador en las peticiones de un servlet.

Introducción
Envio de datos del formulario HTML en la petición HTTP
La etiqueta FORM encierra al resto de etiquetas que pueden componer el formulario. Dispone de los
siguientes atributos:
method= especifica la forma en la que los datos del formulario son enviados. Sus valores son post y
get.

Cuando el método es get, los datos son enviados al servidor como una petición HTTP GET, añadidos
a la url especificada mediante el atributo action; por ejemplo: http://Servlet1?nombre=pepe

Los datos así remitidos tienen un doble límite. Como se envían dentro de una url, deben utilizarse
únicamente caracteres ASCII, y su longitud está limitada a la longitud de la url que el servidor
pueda manejar. La regla general es la de no utilizar el método get si esperamos recibir caracteres no
ASCII o datos de más de 100 caracteres.

Con el método post, los datos son enviados como una petición HTTP POST, en el cuerpo de la
petición. El método usual es post.
action indica el destino de los datos. Aquí es donde debe especificarse una cuenta de correo o un
programa procesador CGI.
enctype=, se usa cuando se ha especificado method=post, para determinar el sistema de
encriptación. Por defecto, si no se incluye este atributo se enviará el formulario con el tipo MIME. Si
se desea no incluir encriptación ninguna, deberá indicarse "text/plain".
Otros atributos de son accept= que permite especificar los caracteres admisibles, y target=
que permite indicar el frame donde se presentan los resultados, si los hay.

Envio por POST


En el siguiente ejemplo creamos un formulario con una caja de texto para que el usuario introduzca
su nombre.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<html>

<head>
<title>PAGINA 1</title>
</head>

<body>
<form name="form1" action= "Servlet1" method="post">
Nombre:<input type="text" name="txtNombre">
<br><input type="submit" value="enviar">
</form>

</body>

</html>
Enviaremos la información del nombre de usuario con el método Post.
El Servet1 recogerá la información que le envían a través del método getParameter(nombre) del
objeto request.
Código Servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Servlet1 extends HttpServlet{

public void doPost(HttpServletRequest request, HttpServletResponse response)_


throws IOException,ServletException{

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Respuesta Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("Hola: "+request.getParameter("txtNombre"));
out.println("</body>");
out.println("</html>");
}
}
El fichero web.xml quedará configurado de la siguiente manera:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" _
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd">
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/Servlet1</url-pattern>
</servlet-mapping>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>pagina1.html</welcome-file>
</welcome-file-list>
</web-app>
Parámetros del protocolo http
Los parámetros de petición son cadenas enviadas por el cliente al contenedor de servlets como parte
de su petición. Los parámetros están almacenados como pares de nombre-valor. Algún nombre
concreto, puede almacenar múltiples valores. Los siguientes métodos de la interfaz ServletRequest
están disponibles para acceder a los parámetros:
getParameter
getParameterNames
getParameterValues: devuelve una matriz de String que contiene todos los valores asociados al
nombre del parámetro.
getParameterMap: devuelve un java.util.Map del parámetro de la petición, que contiene nombres y
valores como un Map.
Atributos
Los atributos son objetos asociados a una petición. Los atributos se utilizan por el contenedor de
servlets para expresar información que de otra manera, no podría ser expresada por la API, o puede
servir para que un servlet le pase la información a otro (a través del RequestDispatcher). Para
trabajar con atributos se utilizan los siguientes métodos de la interfaz ServletRequest:
getAttribute
getAttributeNames
setAttribute
El nombre de un atributo sólo puede estar asociado a un valor.
Envio por GET
En el siguiente ejemplo insertaremos un hipervínculo en la página html. Al pulsar el hipervínculo
llamaremos al Servlet y le pasaremos un parámetro llamado nombre con el valor pepe.

<html>

<head>
<title>PAGINA 1</title>
</head>

<body>
<a href="Servlet1?nombre=pepe"> Pulse para llamar al Servlet1</a>

</body>

</html>
Como no hemos indicado el method por defecto es Get.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Código Servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Servlet1 extends HttpServlet{

public void doGet(HttpServletRequest request, HttpServletResponse response)_


throws IOException,ServletException{

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Respuesta Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("Hola: "+request.getParameter("nombre"));
out.println("</body>");
out.println("</html>");
}
}
El fichero web.xml quedará configurado de la siguiente manera:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" _
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd">
<servlet>
<servlet-name>Servlet1</servlet-name>
<servlet-class>Servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet1</servlet-name>
<url-pattern>/Servlet1</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>pagina1.html</welcome-file>
</welcome-file-list>
</web-app>

Atributos SSL
Si una petición ha sido transmitida sobre un protocolo seguro, por ejemplo HTTPS, la interfaz
ServletRequest proporciona el método isTrue. Si sí se ha utilizado este protocolo, devolverá trae.
Internacionalización
Los clientes pueden opcionalmente indicar al servidor web cuál es el lenguaje que prefieren utilizar.
Esta información es transmitida por el cliente usando la cabecera Accept-Language, además de otros
mecanismos explicados en la especificación 1.1 de HTTP. Los siguientes métodos son
proporcionados por la interfaz ServletRequest para determinar el lugar preferido por el cliente.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
getLocale
getLocales: devuelve una Enumeration de objetos Locales indicando, en orden decreciente
(empezando con el lugar preferido), los lugares que aceptará el cliente.
Codificación de la información de la petición
Actualmente, muchos navegadores no envían una codificación de caracteres cualificada con la
cabecera Content-Type, dejando claro la determinación de la codificación de caracteres para leer las
peticiones http. La codificación por defecto de una petición es la “ISO-8859-1”. Para indicar al
desarrollador que ha ocurrido un error enviando al cliente una codificación de caracteres, el
contenedor devuelve null cuando se invoca el método getCharacterEncoding.
Si el cliente no tiene establecido ninguna codificación de caracteres y la información de la petición
está codificada, puede ocurrir un error. Para remediarlo, se ha añadido un nuevo método a la
interfaz ServletRequest. Se trata del setCharacterEncoding(String enc), que se usa para establecer
la codificación de caracteres.
Class ServletOutputStream
java.lang.Object
|
+--java.io.OutputStream
|
+--javax.servlet.ServletOutputStream
public abstract class ServletOutputStream
extends java.io.OutputStream
Representa un flujo de salida (escritura) a través del cual se genera y se envía la respuesta desde el
servlet al cliente.
Constructor
protected ServletOutputStream()
Se utiliza únicamente en caso de que se cree una clase anónima interna a esta.

Excepciones
ServletException  es un error de ejecución del programa que se genera cuando se produce un
error interno del servlet.
UnavailableException  se genera cuando el servlet no está a disposición del cliente porque se
esté modificando, el servidor este apagado...
Al servidor le llegan muchas peticiones, estando representadas cada una de ellas por un objeto de la
interfaz ServletRequest dice que usuario, contraseña...
Después se crea un objeto Dispatcher (es el objeto que recibe todas las peticiones) redirige la
petición al servlet o al recurso que se ha pedido
Dentro del servidor el sitio web se compone de recursos todos los servlets que se están
ejecutando a la vez dentro del servidor tienen un objeto común que es la interfaz ServletContext
pasa información de un servlet a otro en ejecución.
Cada uno de los servlets individualmente tiene asociado un objeto de la interfaz ServletConfig
Con todo esto se genera la respuesta y se manda. Cada una de las respuestas constituye un objeto
de la interfaz ServletResponse. (Siempre son paginas html)

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Desarrollar un Servlet con getParameterValues
Cuando una página Html envía información con etiquetas que tienen el mismo nombre, tendremos
que recurrir a recuperar la información con el método getParameterValues.
En el siguiente ejemplo creamos tres checkbox con el mismo nombre, “so”.

<html>
<head>
<title>Formulario</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script language="javascript">
function ok(){

if (formulario.nombre.value.length==0)
{
alert("INTRODUZCA NOMBRE!");
}

else if(formulario.apellido_1.value.length==0){
alert("INTRODUZCA Primer Apellido!");
}
else if(formulario.apellido_2.value.length==0){
alert("INTRODUZCA el segundo Apellido!");
}
else if(formulario.domicilio.value.length==0){
alert("INTRODUZCA el Domicilio!");
}
else{
formulario.submit();
}}
</script>
</head>
<body>
<form name="formulario" action="Servlet1 " method="POST">
<center> <H1><B>FICHA DEL CLIENTE</B></H1>
NOMBRE<input type="text" name="nombre" value="" />
PRIMER APELLIDO<input type="text" name="apellido_1" value="" />
SEGUNDO APELLIDO<input type="text" name="apellido_2" value="" /><br>
DOMICILIO<input type="text" name="domicilio" value="" /><br>
CIUDAD<select name="cuidad"><br>
<option>León</option>
<option>Madrid</option>
<option>Sevilla</option>
</select>
<br>
VARÓN<input type="radio" name="sexo" value="varon" />
MUJER<input type="radio" name="sexo" value="mujer" /><br>
<H2>SISTEMA OPERATIVO</H2>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Windows 7<input type="checkbox" name="so" value="W7" />
<br>WINDOWS VISTA<input type="checkbox" name="so" value="vista" />
<br>MAC OS<input type="checkbox" name="so" value="mac" /><br>
<H2>COMENTARIOS</H2><textarea name="comentarios" rows="10" cols="70">

</textarea><br>
<input type="button" value="REGISTRAR" onclick="ok()" />
</center>
</form>
</body>
</html>
El servlet tendrá que recoger los checkbox seleccionados con el método getParameterValues, que
devolverá un array con los elementos que se seleccionaron.
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet1 extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res) _
throws IOException, ServletException {

res.setContentType("text/html");
PrintWriter out = res.getWriter();

if (req.getParameter("so")!=null){
String[] op = req.getParameterValues("so");
String sb= new String();
for (int i = 0; i < op.length; i++) {

sb=sb.concat(op[i]+" ,");
}
//elimino el ultimo
int lon=sb.length();
sb=sb.substring(0, (lon-2));
out.println("<html>");
out.println("<head>");
out.println("<title>Ejemplo 2</title>");
out.println("</head>");
out.println("<body>");
out.println("<center>Sistemas operativos seleccionados:"+sb+"</center>");
out.println("</body>");
out.println("</html>");
}

}
}

Ver Video: Servlet Envío de Parámetros, en la Unidad 3,


en el Módulo 5, en la plataforma elearning

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Laboratorio: Recogida de parámetros
Capturar Elementos Seleccionados:Checkbox
Objetivos:

Recoger información con el método getParameterValues del objeto request.

Enunciado:
 Realizar una página JSP que envie información sobre si misma al pulsar sobre un botón.
 Cuando enviemos información, mostraremos en una etiqueta DIV los elementos
seleccionados.
 Para completar la práctica, debemos dejar marcados los elementos que el usuario haya
seleccionen nuestra página.

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


<%@page import="java.util.*"%>
<html>
<head>
<title>JSP Page</title>
</head>
<body>
<%String[] datos=request.getParameterValues("chkfruta");%>
<%Vector<String> vfrutas = new Vector<String>();%>
<%String[] frutas = new String[] {"Coco","Mandarina","Papaya","Platano"};%>
<table border="1">
<form name="form1" action="index.jsp" method="post">
<%
if (datos==null)
{
for (int i=0;i<frutas.length;i++)
{%>
<tr><td><input type="checkbox" name="chkfruta" value="<%=frutas[i]%>"><%=frutas[i]%></td></tr>
<%}
}else{
for (int i=0;i<datos.length;i++)
{
vfrutas.add(datos[i]);
}
for (int i=0;i<frutas.length;i++)
{
if (vfrutas.indexOf(frutas[i])==-1)
{%>
<tr><td><input type="checkbox" name="chkfruta" value="<%=frutas[i]%>"><%=frutas[i]%></td></tr>
<%}else{%>
<tr><td><input type="checkbox" name="chkfruta" checked
value="<%=frutas[i]%>"><%=frutas[i]%></td></tr>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%}%>
<%}
}%>
<tr><td><input type="submit" name="btnenviar" value="Enviar Datos"></td></tr>
</form>
</table>

<%
if (datos!=null)
{
for (int i=0;i<datos.length;i++)
{%>
<div style="background-color:fuchsia">
Elementos seleccionados:<%=datos[i]%>
</div>
<%}
}
%>
</body></html>

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 4. Desarrollo de Formularios
Dinámicos
Objetivos
 Comprender el ciclo de vida de un serlet
 Localizar el mecanismo de control de errores en formularios Servlet

Introducción ciclo de vida de un Servlet

El ciclo de vida de un Servlet se divide en los siguientes puntos:

1. El cliente solicita una petición a un servidor vía URL.


2. El servidor recibe la petición.
1. Si es la primera, se utiliza el motor de Servlets para cargarlo y se llama al método init().
2. Si ya está iniciado, cualquier petición se convierte en un nuevo hilo. Un Servlet puede manejar
múltiples peticiones de clientes.
3. Se llama al método service() para procesar la petición devolviendo el resultado al cliente.
4. Cuando se apaga el motor de un Servlet se llama al método destroy(), que lo destruye y libera los recursos
abiertos.

Todos los servlet tienen el mismo ciclo de vida, analizaremos cada uno de ellos:
Inicializar un Servlet
Cuando un servidor carga un servlet, ejecuta el método init del servlet. La inicialización se completa
antes de manejar peticiones de clientes y antes de que el servlet sea destruido.
Aunque muchos servlets se ejecutan en servidores multi-thread, los servlets no tienen problemas de
concurrencia durante su inicialización. El servidor llama sólo una vez al método init al crear la
instancia del servlet, y no lo llamará de nuevo a menos que vuelva a recargar el servlet. El servidor
no puede recargar un servlet sin primero haber destruido el servlet llamando al método destroy.
Interactuar con Clientes
Después de la inicialización, el servlet puede manejar peticiones de clientes. Estas respuestas son
manejadas por la misma instancia del servlet por lo que hay que tener cuidado con acceso a
variables compartidas por posibles problemas de sincronización entre requerimientos concurrentes.
Destruir un Servlet
Los servlets se ejecutan hasta que el servidor los destruye, por cierre el servidor o bien a petición
del administrador del sistema. Cuando un servidor destruye un servlet, ejecuta el método destroy
del propio servlet. Este método sólo se ejecuta una vez y puede ser llamado cuando aún queden
respuestas en proceso por lo que hay que tener la atención de esperarlas. El servidor no ejecutará
de nuevo el servlet, hasta haberlo cargado e inicializado de nuevo.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ciclo de vida de Servlet Suspendido
El ciclo de vida de una petición se extiende de modo que la gestión de una única petición puede
englobar múltiples envíos a la cadena de filtros y al método service del servlet. Esto permite que la
gestión de una petición y la generación de una respuesta se retrasen hasta que los recursos estén
disponibles u ocurran o acaben eventos asíncronos.
El ciclo de vida de una petición empieza cuando una pareja petición/respuesta sea despachada por
primera vez. Normalmente, se completa el ciclo de vía de una petición cuando retorna el despacho y
se confirma, se lanza y se finaliza la respuesta. Sin embargo, la extensión permite que una petición
sea suspendida, tal que cuando el dispatch vuelve al contenedor, el ciclo de vida de la petición no
sea completado.
El contenedor mantiene la petición suspendida hasta que o se reanuda o expira por sobrepasar el
tiempo de espera. Entonces la petición se devuelve siendo despachada a la cadena de filtros normal
y al método service del servlet. Este ciclo se puede repetir más de una vez y la suspensión
transforma el mecanismo existente de despacho en un callback asíncrono. Para permitir que este
mecanismo funcione con los frameworks y códigos existentes, se puede usar en cualquier momento
durante el ciclo de vida de la petición y no se deshabilita por la suspensión de la petición.
Eventos del ciclo de vida de un servlet
Objeto Evento Interfase Listener y clase Event
Contexto Inicialización y javax.servlet.ServletContextListener y ServletContextEvent
Web destrucción
Atributo agregado, javax.servlet.ServletContextAttributeListener y
eliminado o remplazado ServletContextAttributeEvent
Session Creación, invalidación, javax.servlet.http.HttpSessionListener,
activación, desactivación javax.servlet.http.HttpSessionActivationListener, y
y tiempo afuera HttpSessionEvent
Atributo agregado, javax.servlet.http.HttpSessionAttributeListener y
eliminado o HttpSessionBindingEvent
reemplazado
Request Un componente Web ha javax.servlet.ServletRequestListener y ServletRequestEvent
comenzado a procesar
una petición a servlet
Atributo agregado, javax.servlet.ServletRequestAttributeListener y
eliminado o remplazado ServletRequestAttributeEvent

Parámetros de inicialización de un Servlet


En la vida de ejecución de un servlet, el servlet, recuperará información de múltiples sitios. Por
ejemplo recibirá en la petición información vía parámetros, recuperará datos de múltiples orígenes:
bases de datos, ficheros,…
Es habitual recuperar información de los parámetros de inicialización del servlet.
Cuando creamos un servlet y lo definimos en el descriptor de despliegue, podemos indicarle que el
servlet lleva asociado parámetros de inicialización y los valores de dichos parámetros.
El uso de estos parámetros es muy potente, ya que se pueden modificar sus valores, con el fin de
obtener un comportamiento diferente del servlet, sin necesidad de recompilar este.
Algunos de los usos de los parámetros de inicialización podrían ser:
 Tiempos de control de peticiones
 Nombres de recursos externos a los que acceder: ficheros, bases de datos,…
 Nivel de log que se quiere aplicar al programa.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
 Siempre suelen ser cosas relativas a la configuración del servlet.
Lo primero que tenemos que hacer es definir en el descriptor de despliegue (/WEB-INF/web.xml) del
servlet:
<servlet>
<description>Ejemplo ...bla bla bla.</description>
<display-name>P1</display-name>
<servlet-name>P1</servlet-name>
<servlet-class>Servlet1</servlet-class>
</servlet>
El servlet se define mediante la etiqueta . Dentro de esta tenemos dos etiquetas
importantes. será el nombre de referencia del servlet y será la clase
java que implementa dicho servlet.
Los parámetros del servlet también se definen dentro de la etiqueta Para ello utilizaremos
la etiqueta . Anidada a este tenemos dos etiquetas: que será el nombre del
parámetro y que será el valor que le demos al parámetro de inicio.
En nuestro ejemplo vamos a definir dos parámetros. El primero será NivelLog que almacenará el tipo
de log con el que grabaremos y NumeroPeticiones que nos pasará un indicador de limitación.
<servlet>
<init-param>
<description>Nivel de log a aplicar</description>
<param-name>NivelLog</param-name>
<param-value>DEBUG</param-value>
</init-param>
<init-param>
<description>Número de peticiones para atender</description>
<param-name>NumeroPeticiones</param-name>
<param-value>8</param-value>
</init-param>
</servlet>
Una vez que hemos definido esto en el descriptor de despliegue, tendremos que acceder a los
valores desde el servlet.
Lo más normal es acceder a esta información en el método init(). Si es que la información aplica a
todas las peticiones del servlet.
Para recuperar los parámetros tenemos que acceder a el método .getInitParameter(String
parámetro) que permite acceder al valor del parámetro pasado como argumento a dicho método.
Ejemplo de inicialización de parámetros en un proyecto con NetBeans:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Controladores de error
El descriptor de implementación nos permite personalizar lo que el servidor envía al usuario cuando
se produce un error. El servidor puede mostrar una ubicación de página alternativa cuando se trata
de enviar un código de estado HTTP concreto o cuando un servlet genera una excepción Java
concreta.
El elemento error-page contiene tanto un elemento error-code con un valor de código de error HTTP
(como por ejemplo 1500) o un elemento con el nombre de clase de la excepción
prevista (como por ejemplo java.io.IOException). También contiene un elemento que
contiene a su vez la ruta de URL del recurso que se va a mostrar cuando se produzca el error.
<error-page>
<error-code>1500</error-code>
<location>/paginasdeerror/ServletError1.jsp</location>
</error-page>
Ejemplo de gestión de errores de un proyecto completo:

Analicemos el elemento error-page con el siguiente ejemplo:


<error-page>
<error-code>404</error-code>
<location>/DatoNoencontrado.htm</location>
</error-page>

<error-page>
<error-code>500</error-code>
<location>/errorNolocalizado.htm</location>
</error-page>

<error-page>
<exception-type>java.sql.SQLException</exception-type>
<location>/ServidorNoDisponible.htm</location>
</error-page>
Las primeras dos declaraciones indican una página de redirección mediante el elemento ,
esta redirección sería llevada a cabo cada vez que el "Servlet" encontrara un error HTTP 404 (Página
no Encontrada) y/o HTTP 500 (Error Interno).
La tercera declaración indica una redirección en base a un error por Clase, en este caso se está
indicando que en caso de surgir un error de tipo java.sql.SQLException se redireccione al usuario a
la página base_nodisponible.htm.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Seguridad
Una aplicación web contiene recursos que pueden ser accedidos por muchos usuarios. Esos recursos
no están protegidos en una red abierta como es Internet. Esto no es permisible para muchas
aplicaciones, que deben tener seguridad.
Aunque la garantía de calidad y los detalles de implementación pueden variar, los contenedores de
servlets tienen mecanismos e infraestructura para congregar esos requerimientos que comparten las
siguientes características:
Autenticación: permite saber si un determinado usuario tiene o no acceso a determinados recursos.
Control para el acceso a los recursos: las interacciones con los recursos están limitadas para
determinados grupos de usuarios o programas para poder así implementar integridad,
confidencialidad, o restricciones de disponibilidad.
Integridad de datos (Data Integrity): asegura que la información no ha sido modificada por un
tercero en la transmisión de los datos.
Confidencialidad o privacidad de datos (Confidentiality or Data Privacy): se asegura que los datos no
podrán ser vistos por personas que no estén autorizadas.

Seguridad declarativa
La seguridad declarativa hace referencia a la estructura de seguridad de una aplicación, en la que
están inmersos los roles, los controles de acceso, los requerimientos de autenticación, pero de una
manera externa a la aplicación. El descriptor de aplicación es el primer vehículo para la seguridad
declarativa en las aplicaciones web. Esto asegura que en tiempo de ejecución, el contenedor de
servlets usa la política de seguridad que se ha establecido para asegurar la autenticación y la
autorización.
El modelo de seguridad se aplica al contenido estático de la aplicación web y a los servlets dentro de
la aplicación que demanda el cliente. El modelo de seguridad no se aplica cuando un servlet usa el
RequestDispatcher para invocar un recurso estático o un servlet, es decir, cuando se usa el método
forward o include.

Seguridad programada
La seguridad programada se usa cuando la seguridad declarativa no es suficiente para el modelo de
seguridad de la aplicación. Este tipo de seguridad consiste en los siguientes métodos
(proporcionados por la interfaz HttpServletRequest):

getRemoteUser: devuelve una cadena con el nombre del usuario que ha hecho la petición y que se
va a autenticar.
isUserInRole: true si el usuario que ha hecho la petición pertenece al grupo o rol que se pasa en el
argumento. False en el caso contrario. El rol se debe crear en el descriptor de aplicación. Para ello se
añade un elemento como el siguiente:

<security-role-ref>: es opcional. Si aparece, puede hacerlo múltiples veces.


Contiene una declaración de seguridad para el servlet dentro del código de la aplicación web.
<description>: es opcional. Si aparece, sólo lo hace una vez.
<role-name>: es obligatorio.
<role-link>: es opcional. Subelemento con información de tipo cadena.
Contiene la declaración o un enlace a donde está definido el papel de seguridad que se va a aplicar
al servlet.
</security-role-ref>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
getUserPrincipal: devuelve un objeto de la clase java.security.
Principal que representa las restricciones principales de seguridad establecidas en la aplicación.
Cuando no hay ninguna restricción devuelve null.

Papeles
Como ya se ha visto, el proceso de comprobación de un usuario dentro de una aplicación se conoce
como autenticación. Por el contrario, al usuario que accede o intenta acceder se le llama agente.
Los agentes se pueden agrupar en grupos por funcionalidad que se denominan roles.
Los agentes y roles permitidos en un servidor web están siempre en un fichero de configuración. En
el Tomcat están en la carpeta conf y el fichero es Tomcat-users.xml
Ejemplo:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="admin"/>
<role rolename="manager"/>
<role rolename="role1"/>
<role rolename="tomcat"/>
<user username="admin" password="" roles="admin,manager"/>
<user username="role1" password="tomcat" roles="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
</tomcat-users>
Con la etiqueta role se definen los roles y con users los usuarios individualmente. Roles es para
formar grupos de roles, separados por comas:
<roles="admin,manager"/> es igual a:
<role rolename="admin"/>
<role rolename="manager"/>
Para añadir otro usuario utilizamos la etiqueta user, indicando nombre y contraseña y si tiene roles.
Autenticación
Consiste en comprobar la seguridad de dos formas:
Mediante código
Dejando que se encargue el contenedor servlet. Ésta a su vez se divide en 4 tipos:
Básica
Basada en formularios
Con resúmenes
SSL (Con certificados de cliente)
Están ordenadas de la menos segura (básica) a la más segura (SSL)
Cuando se trabaja con la seguridad en servlet el subtipo (cualquiera de estas 4) se indica en el
descriptor de distribución
<login-config> se hace a través de este elemento que es subelemento de web-app.
Se utiliza para definir el tipo de autenticación declara en el sitio
<description>: es una breve descripción del modo de seguridad
<auth-method>: obligatorio de una única aparición. Indica el tipo de autenticación
<realm-name>: obligatorio de una única aparición. Se utiliza para establecer
un nombre utilizado por aplicaciones externas
</login-config>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Autenticación básica
Cuando se intenta acceder a un recurso protegido de la aplicación solicitar usuario y contraseña a
través de un cuadro de dialogo de sistema (no lo creamos nosotros sino que sale automáticamente).
En el caso de que el agente este autenticado en la aplicación se le muestra el recurso solicitado, en
caso contrario se le dan tres intentos para conexión trascurridos los cuales se le redirecciona a una
página de error.
Se indica en el elemento <auth-method> del login-config con la palabra BASIC ( <auth-method> BASIC).

Autenticación con resúmenes


Igual que la básica con la diferencia de que el usuario y la contraseña van codificadas
internamente En la petición no va el nombre de usuario o la clave lo que se transmite es un valor
de dispersión.(El valor de dispersión es con los valores reales se les aplica un algoritmo matemática
y da este valor de dispersión.)
Se indica en el elemento <auth-method>del login-config con la palabra DIGEST ( <auth-method>
DIGEST)

Autenticación basada en formularios


Igual que la autenticación básica se conecta a través de usuario y clave. Además aquí la información
tampoco va codificada. La diferencia con la básica, que es su principal característica, es que la
pagina inicial donde va el cuadro de dialogo la crea el desarrollador.
La página de error a la que se redirecciona transcurridos los tres intentos, es una página creada
también por el desarrollador.
Hay tres atributos para esta autenticación:
j_username es la variable que contiene el nombre o identificador de usuario
j_password es la variable que contiene el valor de la clave
j_security_check contiene el nombre de la acción del formulario de identificación
Nosotros tenemos que poner a las cajas de texto donde vamos a recoger usuario y contraseña,
como nombre j_username y j_password. Tenemos que llamarlas así, sino no funciona.
Y en el atributo action del formulario tenemos que poner j_security_check.
Ejemplo:
Entrada.jsp
<form action=’j_security_check’>
<input type=’text’ name=’j_username’>
<input type=’password’ name=’j_password’>
</form>
Cuando pulsamos el submit lo que hace es recoger el valor de estas dos cajas y comprobarlo con los
usuario que tengan acceso a las paginas.
Se indica en:
<login_config>
<description>
<auth-method> FORM
<form_login_config>
<form_login_page>
<form_error_page>
<form_login_config>
</login_config>
Tenemos que añadir el elemento .

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
El form_login_page contiene la página que se va a mostrar una vez autenticado el usuario.
El form_error_page contiene la página que se va a mostrar si se produce un error.
Estas dos páginas tenemos que crearlas nosotros.
Restricciones de seguridad
Las restricciones de seguridad son una manera declarativa de definir el nivel de protección o
seguridad de contenido web.
Una restricción de seguridad asocia la autorización (o restricción de datos) de un usuario con
operaciones HTTP dentro de la aplicación web. La restricción consta de los siguientes elementos:
Colección de recursos web.
Restricción de autorización.
La restricción de datos del usuario.
Las operaciones HTTP y los recursos web se identifican por una o más colección de recursos. Éstas
se dividen en los siguientes elementos:
Patrón URL.
Métodos HTTP.
Una restricción de seguridad establece un requisito de autenticación para permitir a la petición
acceder a determinados recursos. Un usuario debe pertenecer al menos, a uno de los roles que
están definidos en el descriptor de aplicación. Si no es así, no se permite su acceso bajo ningún
aspecto. Una restricción de seguridad se compone de los siguientes elementos:
Nombre de rol: Una restricción de datos de usuario establece como requisito, que todas las
peticiones que lleguen, lo hagan sobre una conexión protegida. La magnitud de esta protección,
viene dada por el valor de la garantía de transporte. Un transporte se dice que tiene garantía
INTEGRAL cuando sólo se asegura el transporte. La garantía CONFIDENTIAL se usa para asegurar la
confidencialidad de los datos. Por el contrario, la garantía “NONE” indica que el contenedor debe
aceptar cualquier tipo de petición, incluso las que no están protegidas.
Garantía del transporte: Si no se aplica una restricción de autenticación a una petición, el
contenedor debe aceptarla sin requerir la identificación del usuario. Si a la petición no se le aplica
una restricción de datos, el contenedor debe aceptarla siempre que reciba una conexión, aunque
esta esté sin protección.
Políticas por defecto.
Por defecto, la autenticación no es necesaria para acceder a los recursos. Sólo se hará cuando se
especifique en el descriptor de aplicación.
Las características de la conexión admitida, debe satisfacer al menos, las restricciones que fueron
establecidas. Si no es así, el contenedor la rechazará y la redireccionará a un puerto HTTPS.
Si el usuario no está autenticado, la petición será rechazada enviando el código de error 401
(SC_UNAUTHORIZED).

Ver Video: Ciclo de Vida Servlet, en la Unidad 4,


en el Módulo 5, en la plataforma elearning
Laboratorio: Ciclo de vida de un servlet
Objetivos:
Entender el ciclo de vida de un servlet.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Enunciado:
Sobreescribir los métodos init, destroy, post, get y service en un servlet.
1. Abrir un proyecto web y agregar un fichero Servlet.
2. Sobreescribir los métodos como se indica en el siguiente código para entender el ciclo de vida
de un servlet.
import java.sql.*;
import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;

public class ServletCiclodeVida extends HttpServlet{

public void service (HttpServletRequest peticion, HttpServletResponse respuesta) _


throws IOException,ServletException{

if(peticion.getMethod().equals("GET")){
doGet(peticion,respuesta);
}else if(peticion.getMethod().equals("POST")){
doPost(peticion,respuesta);
}
}

public void init(ServletConfig config) throws ServletException


{
}
public void destroy()
{
}

public void doGet (HttpServletRequest peticion, HttpServletResponse respuesta) _


throws IOException,ServletException{
Gestionar(peticion,respuesta);
}

public void doPost (HttpServletRequest peticion, HttpServletResponse respuesta) _


throws IOException,ServletException{
Gestionar(peticion,respuesta);
}

public void Gestionar (HttpServletRequest peticion, HttpServletResponse response) _


throws IOException,ServletException{

try{

ServletOutputStream out = response.getOutputStream();


response.setContentType("text/html");

out.println("<html>");
out.println("<head>");
out.println("<title> </TITLE>");
out.println("</HEAD>");
out.println("<BODY> Métodos del ciclo de vida");

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
out.println("</body>");
out.println("</html>");
out.close();

}catch( Exception e){


System.out.println("\n\tERROR: "+ e.toString());
}
}
}
import java.io.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletContador extends HttpServlet{

static DataOutputStream escribir;


static DataInputStream leer;
static File archivo;
static int contador;

//------------------------------------------
public void doGet (HttpServletRequest peticion, HttpServletResponse respuesta) _
throws IOException, ServletException{
Gestionar(peticion, respuesta);
}
//------------------------------------------
public void doPost (HttpServletRequest peticion, HttpServletResponse respuesta) _
throws IOException, ServletException{
Gestionar(peticion, respuesta);
}

//------------------------------------------
public void Gestionar (HttpServletRequest peticion, HttpServletResponse respuesta) _
throws IOException, ServletException{
archivo = new File ("C:\\EJFundamentos\\Visitas.txt");
DecimalFormat formato = new DecimalFormat("00000");
//para dar formato decimal

if(!archivo.exists()){
escribir= new DataOutputStream _
(new FileOutputStream("C:\\EJFundamentos\\Visitas.txt"));
try{
escribir.writeInt(0);
escribir.close();
}catch (IOException e){}
}else{
leer = new DataInputStream (new FileInputStream (archivo));
try{
contador= leer.readInt();
leer.close();
}catch (IOException e){}

}
escribir = new DataOutputStream _
(new FileOutputStream("C:\\EJFundamentos\\Visitas.txt"));
try{

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
escribir.writeInt(++contador);
escribir.close();
}catch (IOException e){}

ServletOutputStream flujo = respuesta.getOutputStream();


respuesta.setContentType("text/html");

flujo.println("<HTML>");
flujo.println("<HEAD>");
flujo.println("<TITLE>RESPUESTA</TITLE>");
flujo.println("</HEAD>");
flujo.println("<BODY TEXT=#FFFFFF BGCOLOR=#000080 _
LINK = #FFFFFF ALINKCYAN VLINKORANGE><CENTER>");
flujo.println("<FONT FACE=ARIAL");
String s_cont= formato.format(contador);
flujo.println("<br><h2>Estado del contador de visitas:<br><br>");
flujo.println("<table border=2 align=center width=5% height=1% _
cellsapcing=2 border=1 cellpadding=3>");
flujo.println("<tr align=center><td><h2>"+ s_cont+"</h2></td></tr></table>");
flujo.println("</font></center></body>");
flujo.println("</html>");
flujo.close();
}

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 5 . Uso compartido de recursos de la
aplicación con el contexto servlet
Introducción

El contexto en donde los componentes Web se ejecutan es un objeto que implementa la interfase ServletContext.
Se puede recuperar el contexto Web utilizando el método getServletContext. El contexto Web proporciona
métodos para acceder a:

 Parámetros de inicialización
 Recursos asociados con el contexto Web
 Atributos como objetos
 Habilidades de registro
Un contexto está asociado a un objeto ServletContext, que está contenido en un objeto
ServletConfig. Es utilizado para compartir datos entre todos los servlets y jsps de una aplicación.
Proporciona al programador:
Un contenedor virtual para almacenar objetos a los que pueden acceder todos los servlets y jsps de
una misma aplicación web. En este sentido, se emplea para pasar datos de un servlet a otro. Es
importante resaltar que hay un contexto por cada aplicación web.
Interfaces que permiten comunicarse con el entorno de ejecución de la aplicación web, es decir, con
el contenedor web, por ejemplo, para obtener el tipo MIME de un fichero, para escribir en un fichero
log del servidor, para obtener un objeto RequestDispatcher usado para delegar en otros recursos el
procesamiento de la petición, para conocer la ruta asociada al directorio raíz de una aplicación web,
etc. Consultar la API.
el contexto de una aplicación web se obtiene mediante el método ServletContext
getServletContext() de la interface ServletConfig o mediante getServletContext () de GenericServlet.
Se obtiene un contexto vacío, todavía no contiene elementos.
Los atributos se agregan al contexto de una aplicación web mediante el método de la interface
javax.servlet.ServletContext void setAttribute(String clave, Object valor). Se asigna una clave y un
valor asociado a la misma. La clave debe ser una String y el valor un Object.

Objetivos
 Describir la finalidad del contexto servlet
 Trabajar con el contexto de un servlet.

Describir la finalidad y las funciones del contexto


servlet.
Interfaz ServletContext
Representa el contexto de ejecución del servlet dentro del servidor web. Permite comunicar y pasar
información entre diferentes servlets que corren en el mismo servidor, comunicarse con el propio
servidor web y generar ficheros con mensajes introducidos desde el servlet. Toda aplicación web
tiene un único ServletContext, y es accesible por todos los recursos activos de la aplicación.
Los métodos más importantes son getResource() y getResourceAsStream(), que son usados por los
servlets para acceder a cualquier recurso sin importar dónde resida dicho recurso. La siguiente tabla
proporciona una breve descripción de estos métodos (para mas información, consultar la API):

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Método Descripción
Java.net.URL getResource(String Devuelve un objeto de la clase java.net.URL
path) para el recurso mapeado por la ruta
proporcionada. La ruta debería empezar con
/ si no es una ruta absoluta (relativa al
documento root). Por ejemplo, si pasas una
ruta de un archivo JSP, te devolverá los
datos no procesados, en este caso, el código
JSP, cuando se lea el contenido.
java.io.InputStream Este método es un shortcut si quieres
getResourceAsStream(String path) obtener un InputStream de un recurso. Es
equivalente a
getResource(path).openStream().

Ámbito de la interfaz ServletContext


Por defecto, existe una instancia de un objeto de la interfaz ServletContex para cada aplicación web
dentro de un contenedor. Éste, forma parte de manera implícita. En los casos donde el contenedor
está distribuido sobre múltiples máquinas virtuales (VM), una aplicación web debería tener una
instancia del ServletContext por cada máquina virtual. Es decir, el objeto ServletContext es
individual para cada máquina virtual, no pudiendo compartir la información entre ellos.

Inicialización de parámetros
Los siguientes métodos de la interfaz ServletContext permiten el acceso a los parámetros de
inicialización del servlet asociados con la aplicación web especificada en el descriptor de aplicación:
getInitParameter.
getInitParameterNames.

Atributos
Un servlet puede añadir atributos al objeto de la interfaz ServletContext. Cuando se hace esto, el
atributo estará disponible para el resto de servlets que se encuentren en la misma aplicación web.
Los siguientes métodos de la interfaz ServletContext permiten este cometido:
 setAttribute
 getAttribute
 getAttributeNames
 removeAttribute
Se ha de tener en cuenta, que los atributos son locales a cada máquina virtual, por lo que si se
necesita compartir información en un entorno distribuido, la información debería almacenarse en
una sesión, en una base de datos o en un Enterprise JavaBean.

Recursos
Podemos ver la interfaz ServletContext como una ventana para la visualización del entorno de un
servlet. Un servlet puede utilizar esta interfaz para conseguir información, tal como parámetros de
inicialización para las aplicaciones web de la versión del contenedor. Esta interfaz también
proporciona métodos de utilidad para recuperar el tipo MIME de un archivo, recursos compartidos,
para logeo, y demás. Toda aplicación web tiene un único ServletContext, y es accesible en todos los
recursos activos de la aplicación. También es usado por los Sevlets para compartir datos entre ellos.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Es importante tener conocimientos sólidos de esta interfaz puesto que el examen contiene
numerosas preguntas acerca de ella.
En esta sección, estudiaremos los métodos getResource() y getResourceAsStream(). Estos métodos
son usados por los servlets para acceder a cualquier recurso sin importar dónde reside actualmente
dicho recurso. La siguiente tabla proporciona una breve descripción de estos métodos, para más
información consultar la API:
Método Descripción
java.net.URL getResource(String Devuelve un objeto de la clase java.net.URL
path) para el recurso mapeado por la ruta
proporcionada. La ruta debería empezar con
/ si no es una ruta absoluta (relativa al
documento root). Por ejemplo, si pasas una
ruta de un archivo JSP, te devolverá los
datos no procesados, en este caso, el código
JSP, cuando se lea el contenido.
java.io.InputStream Este método es un shortcut si quieres
getResourceAsStream(String path) obtener un InputStream de un recurso. Es
equivalente a
getResource(path).openStream().

Recarga
Para que la aplicación se comporte como espera el desarrollador, se debe asegurar que todos los
servlets y clases que se vayan a usar en ella, estén cargados en el ámbito de un solo cargador de
clase. Como ayuda al desarrollo, el contenedor notifica si una sesión se añade o se termina.

Elementos del path de la petición


El path de la petición a un servicio servlet, está compuesto de muchas secciones importantes. Los
siguientes elementos son obtenidos del path URI de la petición y mostrados a través del objeto de la
petición:
El Path de contexto: es el prefijo del path - asociado con el ServletContext - del que este servlet
forma parte. Si este es el contexto por defecto en la base del espacio de nombres URL del servidor
web, este path debería ser una cadena vacía. De otra manera, si el contexto no está en la raíz del
espacio de nombres del servidor, el path empieza con una carácter “/”, pero no acaba con un
carácter “/”.
Servlet Path: es la sección del path que se corresponde directamente con el mapeo que activa la
petición. Este path empieza con un carácter “/” excepto en el caso que la petición coincida con el
patrón “/*”, en cuyo caso es la cadena vacía.
PathInfo: es la parte del path de la petición que no es parte del Context Path o el Servlet Path.
Camino Context o el Servlet Path. En el caso de ser nulo (si no hay path extra), o es un cadena con
un dirección “/”. Los siguientes métodos existen en la interface HttpServletRequest para acceder a
esta información.
 getContextPath
 getServletPath
 getPathInfo
Es importante hacer notar que, excepto para la codificicación URL, las diferencias entre el URI de
petición y las partes del path hacen que siempre se cumpla la siguiente ecuación:
requestURI = contextPath + servletPath + pathInfo

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Interface ServletContext
public abstract interface ServletContext
Representa el contexto de ejecución del servlet dentro del servidor web. Permite comunicar y pasar
información entre diferentes servlets que corren en el mismo servidor, comunicarse con el propio
servidor web y generar ficheros con mensajes introducidos desde el servlet.

Interface ServletContext de java


package javax.servlet;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;

public interface ServletContext {

public ServletContext getContext(String uripath);

public String getContextPath();

public int getMajorVersion();

public int getMinorVersion();

public String getMimeType(String file);

public Set getResourcePaths(String path);

public URL getResource(String path) throws MalformedURLException;

public InputStream getResourceAsStream(String path);

public RequestDispatcher getRequestDispatcher(String path);

public RequestDispatcher getNamedDispatcher(String name);

public Servlet getServlet(String name) throws ServletException;

public Enumeration getServlets();

public Enumeration getServletNames();

public void log(String msg);

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public void log(Exception exception, String msg);

public void log(String message, Throwable throwable);

public String getRealPath(String path);

public String getServerInfo();

public String getInitParameter(String name);

public Enumeration getInitParameterNames();

public Object getAttribute(String name);

public Enumeration getAttributeNames();

public void setAttribute(String name, Object object);

public void removeAttribute(String name);

public String getServletContextName();


}

Métodos
java.lang.Object getAttribute(java.lang.String name)
Devuelve un object que corresponde al valor del atributo cuyo nombre se
pasa como argumento. Si el atributo no existe devuelve null.
java.util.Enumeration getAttributeNames()
Devuelve un objeto enumeration donde cada elemento es un String que
corresponde al nombre del atributo del Servlet. En caso de que no haya
ninguno devolvería una enumeración vacía
ServletContext getContext(java.lang.String uripath)
Devuelve un objecto de la interfaz.
int getMajorVersion()
Devuelve un entero que corresponde a la ultima versión de la API referente
al servlet que esta soportada en el servidor web.
java.lang.String getMimeType(java.lang.String file)
Devuelve un String que indica el tipo mime del fichero que se pasa como
argumento. Si no se puede determinar devuelve null. (tipo mime la
codificación interna que lleva un fichero para que a la hora de cargarse en
una aplicación se interprete de una forma u otra)
int getMinorVersión()
Devuelve un int que corresponde a la versión mas baja del api del servlet
que soporta el servidor web
java.lang.String getRealPath(java.lang.String path)
Devuelve un String que indica la ruta completa donde se encuentra el
recurso que se pasa como cadena en el argumento.
RequestDispatcher getRequestDispatcher(java.lang.String urlpath)
Devuelve un objeto de la interfaz RequestDispatcher que corresponde al
recurso que se pasa como cadena en el argumento. Con este objeto se
puede redireccionar e incluir otros recursos que utilizasen el recurso pasado
en el argumento de la función (se utiliza para saber cuando se llama a un
servlet desde otro)
java.net.URL getResource(java.lang.String path)
Este método devuelve una URL que corresponde al recurso cuyo path se

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
pasa como cadena en el argumento o null en el caso de que no exista.
A partir de tener la URL tenemos el método openConnection para abrir una
conexión desde el recurso.
java.io.InputStream getResourceAsStream(java.lang.String path)
La diferencia con el anterior es que este método devuelve un objeto
InputStream que corresponde o esta asociado al recurso cuyo path se pasa
como cadena en el argumento. Si no existe el recurso devuelve null. En
caso contrario, si devuelve el objeto inputStream puedes utilizar el flujo de
lectura para leer desde el servlet el contenido del recurso
java.lang.String getServerInfo()
Devuelve un String que indica el servidor web y la versión en la cual esta
corriendo el servlet
void log(java.lang.String msg)
Escribe en un fichero asociado al servlet la cadena que se pasa como
argumento
void log(java.lang.String message, java.lang.Throwable throwable)
El primer argumento es lo mismo que en el anterior método y el segundo
argumento es un objeto de la clase thowable o derivada suya que se ha de
generar al escribir dicho mensaje en el fichero.
Se utiliza siempre que se utilice propagación o captura de excepciones (try
catch finally)
Por defecto cualquier tipo de recurso que se cree desde un servlet se crea
desde la raiz
void removeAttribute(java.lang.String name)
Para eliminar del contexto del servlet el recurso cuyo nombre se pasa como
argumento
void setAttribute(java.lang.String name, java.lang.Object object)
Para establecer dentro del contexto del servlet un atributo cuyo nombre se
pasa como cadena en el primer argumento y cuyo valor se pasa como
object en el segundo argumento

ServletContext representa el entorno donde se ejecuta el servidor, es decir, el Servlet Container


Se puede obtener una referencia a él mediante el método ServletConfig.getServletContext()
Algunos métodos que se pueden utilizar son:
 getMajorVersion  de la Servlet API soportada por el contenedor
 getMinorVersion
 setAttribute  guarda un objeto en el ServletContext
 getAttributeNames
 getAttribute
 removeAttribute
A través del contexto de un servlet se puede compartir estado entre varios servlets.
Ejemplo del uso de métodos de la interface ServletContext:
ServletConfig servletConfig;
public void init(ServletConfig config) throws ServletException {
servletConfig = config;
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {

ServletContext servletContext = servletConfig.getServletContext();

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Enumeration attributes = servletContext.getAttributeNames();
while (attributes.hasMoreElements()) {
String attribute = (String) attributes.nextElement();
System.out.println("Attribute name : " + attribute);
System.out.println("Attribute value : " +
servletContext.getAttribute(attribute));
}
System.out.println("Major version : " + servletContext.getMajorVersion());
System.out.println("Minor version : " + servletContext.getMinorVersion());
System.out.println("Server info : " + servletContext.getServerInfo());
}

Eventos ServletContext
En la siguiente imagen podemos apreciar todos los eventos que se producen en el ciclo de vida de
un Servlet.

Interface ServletContextListener
Un objeto de esta interface recibe los eventos de creación y destrucción del contexto servlet. El
contenedor crea el contexto del servlet como paso previo a servir cualquier contenido de la
aplicación.
La clase que implemente esta interface debe estar definida en el archivo web.xml, a través del
elemento

Métodos
void contextDestroyed(ServletContextEvent sce)
Notifica que el contexto del servlet está a punto de ser cerrado.
void contextInitialized(ServletContextEvent sce)
Notifica que el uso del recurso web está listo para ser solicitado.

Ver Video: ServletContext, en la Unidad 5,


en el Módulo 5, en la plataforma elearning

Actividades
www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

Unidad 6 . Diseño de la Capa de Negocio


Objetivos
 Entender la separación de la lógica de negocios y de la lógica de diseño
 Trabajar con los distintos modelos de capas.

Introducción
La programación por capas es un estilo de programación en la que el objetivo primordial es la
separación de la lógica de negocios de la lógica de diseño, un ejemplo básico de esto es separar la
capa de datos de la capa de presentación al usuario. Es la alternativa más radiacal al modelo
centralizado que consiste en un conjunto de terminales brutas que se conectan a un Mainframe
todas la operaciones se realizan en ésta, mientras que las terminales solo se emplean como
interface.
Entre los motivos por los cuales se recurre a la arquitectura multicapas se cuentan los siguientes:
• Aislamiento de la lógica de aplicaciones en componentes independientes susceptibles de
reutilizarse después en otros sistemas; distribución de las capas en varios nodos físicos de
cómputo y en varios procesos. Esto puede mejorar el desempeño, la coordinación y el
compartir la información en un sistema de cliente-servidor.
• Asignación de los diseñadores para que construyan determinadas capas; por ejemplo, un
equipo que trabaje exclusivamente en la capa de presentación. Y así se brinda soporte a los
conocimientos especializados en las habilidades de desarrollo y también a la capacidad de
realizar actividades simultáneas en equipo.

En toda arquitectura de capa los elementos agrupados en una misma capa pueden comunicarse
entre sí; pero existen variantes en cuanto a las comunicaciones permitidas entre elementos de
capas diferentes:
Arquitectura top-down de capas: Los elementos de una capa i+1 pueden enviar solicitudes de
servicio a elementos de la capa inferior i. Típicamente se produce una cascada de solicitudes, es
decir para satisfacer una solicitud a una capa i+2, ésta requiere enviar varias solicitudes a la capa
i+1; cada una de estas solicitudes a la capa i+1 genera a su vez un conjunto de solicitudes a la capa
i y así sucesivamente. Una arquitectura top-down es laxa (o no estricta) si los elementos de una
capa i+1 pueden enviar solicitudes de servicio directamente a un elemento de cualquiera de las i
capas inferiores.

Arquitectura bottom-up de capas: Cada elemento de una capa i puede notificar a elementos de
la capa superior i+1 de que ha ocurrido algún evento de interés (ej. manejadores de dispositivos).
La capa i+1 puede juntar varios eventos antes de notificar a su vez an elemento de la capa i+2. Una
arquitectura bottom-up tambien puede ser no estricta si el elemento de la capa i puede notificar a
cualquier elemento de cualquier capa superior a la capa i.

Arquitectura bidireccional de capas: En su forma más común involucra dos pilas de N


capas que se comunican entre si. El ejemplo más conocido es el de los protocolos en Redes de
Computadores.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Al implementar una arquitectura top-down de capas, se deben tomar en cuenta los siguientes
factores:
¿Cuál es el criterio de abstracción para agrupar servicios/clases en una capa?
Mencionar el criterio Presentación-Dominio de Aplicación-Repositorio de Sistemas de Información.

Determinar el número de capas En términos simplistas, a más capas más flexibilidad pero menor
desempeño.
Típicamente las capas más internas ofrecen menos servicios. Esto ayuda la reutilización de capas.

El grado de encapsulamiento de las capas. A mayor encapsulamiento, menor dependencia externa


sobre la estructura de una capa.
Estructura interna de cada capa. ¿Cuánta información pasar de una capa a otra? Tomemos el caso
de la arquitectura top-down. Es muy posible que, de acuerdo con el tipo de servicio solicitado, la
capa inferior requiera una cantidad de información variable. En un modelo puro "empujado" (push),
la capa superior está obligada a enviarle toda la información que pueda llegar a hacerle falta a la
capa inferior en la solicitud.
Esto no siempre es posible (piense por ejemplo en una solicitud de servicio a una base de datos que
no logra completarse por estar fuera de línea. ¿Qué se hace: reintentar, abandonar, usar una fuente
alterna?).
En el modelo contrario, "halado" (pull o por demanda), la capa inferior solicita mayor información
sólo si le hace falta --¿pero de quién la pida? El modelo de solicitudes top-down presupone un
invocador anónimo y un invocado conocido.
La solución la proporciona el patrón Editorial-Suscriptor (Publish-Subscribe) que encapsula la idea
del callback. Este patrón de diseño lo estudiaremos más adelante.
Diseñar la estrategia de manejo de errores. Este es un aspecto que es frecuentemente obviado,
aunque tiene impacto fuerte tanto en el tiempo de procesamiento como en el esfuerzo de
programación. Típicamente se recomienda manejar el error en el nivel que lo descubrió, si esto no
es posible, dejar que lo resuelva la capa más arriba, pero generalmente abstrayendo el tipo de error
para que sea comprensible en término de los servicios de la capa superior.
Todo patrón tiene ventajas y desventajas: en el caso de la arquitectura de capas ya las hemos
mencionado:
• Ventajas
• Reutilización de capas;
• Facilita la estandarización
• Dependencias se limitan a intra-capa
• Contención de cambios a una o pocas capas
Desventajas:
A veces no se logra la contención del cambio y se requiere una cascada de cambios en varias capas;
Pérdida de eficiencia;
Trabajo innecesario por parte de capas más internas o redundante entre varias capas;
Dificultad de diseñar correctamente la granularidad de las capas.
Existen tres propuestas de arquitecturas de capas para Sistemas de Información, donde las capas a
veces reciben el nombre de niveles (en Inglés tiers):
• Arquitectura de dos capas;
• Arquitectura de tres capas;

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
• Arquitectura de cuatro capas.

Arquitectura Aplicaciones J2EE


Las aplicaciones J2EE se basan completamente en el modelo de aplicaciones de 4 niveles.
Todas las aplicaciones constan de 3 partes basicas, que son
Modulos EJB: encargado de tener la logica del negocio y transacciones. En otras palabras podemos
decir que es el encargado de ejecutar programas, consultas a la base de dato principalmente. (capa
Negocio)
Modulo WAR: que es la encargada de tener todos los elementos de interfaz como paginas web,
servlets, applets. (capa WEB).
Aplicación EAR: contiene en su interior toda la configuracion de la aplicación
J2EE, eso incluye el modulo WAR y EJB.

Las etapas del análisis y del diseño orientado a


objetos
Aunque no siempre están bien delimitadas las etapas de análisis y diseño en la POO, se pueden
sintetizar de alguna forma las ideas claves de las distintas tecnologías existentes dentro del
desarrollo orientado a objetos al que denominaremos diseño.
Así, se considera que las etapas del proceso en un desarrollo orientado a objetos son:

Estas etapas suelen seguirse por la mayoría de los métodos de diseño OO existentes.
De hecho, para los sistemas orientados a objetos se suelen definir según el siguiente formato en
pirámide.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
La capa del subsistema. Contiene una representación de cada uno de los subsistemas que le
permiten al software conseguir los requisitos definidos por el cliente e implementar la
infraestructura técnica que los soporta.

La capa de clases y Objetos. Contiene las jerarquías de clase que permiten crear el sistema
usando generalizaciones y especializaciones mejor definidas. Esta capa también contiene
representaciones de diseño para cada objeto.

La capa de mensajes. Contiene los detalles que le permiten a cada objeto comunicarse con sus
colaboradores. Esta capa establece las interfaces externas e internas para el sistema.

La capa de responsabilidades. Contiene las estructuras de datos y el diseño de algoritmos para


todos los atributos y operaciones de cada objeto. Esta pirámide de diseño se centra entonces en
el diseño de un producto o sistema específico.

Al igual que el diseño de software convencional, el DOO aplica diseño de datos (cuando se
representan atributos), diseño de interfaces (cuando se presenta el intercambio de mensajes) y
diseño procedimental (en el diseño de operaciones), no obstante el diseño arquitectónico es
diferente. La arquitectura de diseño OO se centra más en las colaboraciones entre los objetos que
con el flujo de control de datos. De esta manera las capas de la pirámide se renombran para reflejar
de forma más exacta la naturaleza del DOO. La siguiente figura muestra ahora la correspondencia
entre el AOO con las correspondientes capas de la pirámide de diseño OO.

Algunos criterios nos permiten juzgar la capacidad que posee un método de diseño en poder lograr
ciertos elementos importantes tales como la modularidad:

Descomposición. Facilidad con la cual un método de diseño ayuda al diseñador a descomponer un


gran problema en microproblemas más sencillos de resolver.

Composición. Grado con el cual un método de diseño asegura que los componentes de un
programa (módulos), una vez diseñados y construidos, pueden reusarse para crear otros sistemas.

Comprensibilidad. Facilidad de comprensión de un componente de programa sin referencia a otra


información o módulos.

Continuidad. Facilidad de hacer pequeños cambios en un programa y hacer que estos se


manifiesten por sí mismos en cambios correspondientes solamente en no o unos pocos módulos
más.

Protección. Característica arquitectónica que reducirá la propagación de efectos colaterales si


ocurre un error en un módulo dado.

Estos criterios y principios de diseño pueden aplicarse a cualquier método de diseño, incluyendo el
antiguo diseño estructurado. No obstante, el método de diseño orientado a objetos logra cada uno
de los principios de manera más eficiente que otros enfoques y el resultado final es una arquitectura
modular que permite cumplir con todos los principios de modularidad de una manera más eficiente.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Modelo Tres Capas
En una arquitectura de tres niveles, los términos "capas" y "niveles" no significan lo mismo ni son
similares. El término "capa" hace referencia a la forma como una solución es segmentada desde el
punto de vista lógico:
Presentación/ Lógica de Negocio/ Datos.
En cambio, el término "nivel", corresponde a la forma en que las capas lógicas se encuentran
distribuidas de forma física. Por ejemplo:
Una solución de tres capas (presentación, lógica, datos) que residen en un solo ordenador
(Presentación+lógica+datos). Se dice, que la arquitectura de la solución es de tres capas y un nivel.
Una solución de tres capas (presentación, lógica, datos) que residen en dos ordenadores
(presentación+lógica, lógica+datos). Se dice que la arquitectura de la solución es de tres capas y
dos niveles.
Una solución de tres capas (presentación, lógica, datos) que residen en tres ordenadores
(presentación, lógica, datos). La arquitectura que la define es: solución de tres capas y tres niveles.
Es el sucesor de la arquitectura de dos capas, ésta implementa una ó n capas adicionales las cuales
se encargan de encapsular las reglas del negocio asociadas con el sistema y las separa de la
presentación y del código de la D.B.

El modelo de 3 capas es una forma lógica de agrupar los componentes que creamos. Está basado en
el concepto de que todos los niveles de la aplicación, son una colección de componentes que se
proporcionan servicios entre sí o a otros niveles adyacentes. La única comunicación que no está
permitida es la de Frond-End con Back-End.
Los servicios se forman de componentes: El modelo de 3 capas está destinado a ayudarnos a
construir componentes físicos a partir de los niveles lógicos. Así que podemos empezar tomando
decisiones sobre qué parte lógica de la aplicación vamos a encapsular en cada uno de nuestros
componentes de igual modo que encapsulamos los componentes en varios niveles.
Un nivel está conformado por varios componentes, por tanto puede suplir varios servicios.
Niveles del modelo:
Nivel de Usuario: es la que ve el usuario, presenta el sistema al usuario, le comunica la
información y captura la información del usuario dando un mínimo de proceso (realiza un filtrado
previo para comprobar que no hay errores de formato). Esta capa se comunica únicamente con la
capa de negocio. Los componentes del nivel de usuario, proporcionan la interfaz visual que los
clientes utilizarán para ver la información y los datos. En este nivel, los componentes son
responsables de solicitar y recibir servicios de otros componentes del mismo nivel o del nivel de
servicios de negocio.Es muy importante destacar que, a pesar de que las funciones del negocio
residen en otro nivel, para el usuario es transparente la forma de operar.
Nivel de Negocios: es donde residen los programas que se ejecutan, recibiendo las peticiones del
usuario y enviando las respuestas tras el proceso. Se denomina capa de negocio (e incluso de lógica
del negocio) pues es aquí donde se establecen todas las reglas que deben cumplirse. Esta capa se
comunica con la capa de presentación, para recibir las solicitudes y presentar los resultados, y con la
capa de datos, para solicitar al gestor de base de datos para almacenar o recuperar datos de él.
Como los servicios de usuario no pueden contactar directamente con el nivel de servicios de datos,
es responsabilidad de los servicios de negocio hacer de puente entre estos. Los objetos de negocio

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
proporcionan servicios que completan las tareas de negocio tales como verificar los datos enviados
por el cliente. Antes de llevar a cabo una transacción en la D.B. Los componentes de los servicios de
negocio también nos sirven para evitar que el usuario tenga acceso directo a la base de datos, lo
cual proporciona mayor seguridad en la integridad de ésta.
Nivel de Datos: es donde residen los datos. Está formada por uno o más gestor de bases de datos
que realiza todo el almacenamiento de datos, reciben solicitudes de almacenamiento o recuperación
de información desde la capa de negocio. El nivel de datos se encarga de las típicas tareas que
realizamos con los datos: Inserción, modificación, consulta y borrado. La clave del nivel de datos es
que los papeles de negocio no son implementados aquí. Aunque un componente de servicio de
datos es responsable de la gestión de las peticiones realizadas por un objeto de negocio. Un nivel de
servicios de datos apropiadamente implementado, debería permitir cambiar su localización sin
afectar a los servicios proporcionados por los componentes de negocio.
Ventajas:
 Los componentes de la aplicación pueden ser desarrollados en cualquier lenguaje.
 Los componentes son independientes.
 Los componentes pueden estar distribuidos en múltiples servidores.
 La D.B. es solo vista desde la capa intermedia y no desde todos los clientes.
 Los drivers del D.B. No tienen que estar en los clientes.
 Mejora la administración de los recursos cuando existe mucha concurrencia.
 Permite reutilización real del software y construir aplicaciones escalables.

La ventaja principal de este estilo, es que el desarrollo se puede llevar a cabo en varios niveles y en
caso de algún cambio sólo se ataca al nivel requerido sin tener que revisar entre código mezclado.
Un buen ejemplo de este método de programación seria: Modelo de interconexión de sistemas
abiertos
Además permite distribuir el trabajo de creación de una aplicación por niveles, de este modo, cada
grupo de trabajo está totalmente abstraído del resto de niveles, simplemente es necesario conocer
la API que existe entre niveles.
En el diseño de sistemas informáticos actual se suele usar las arquitecturas multinivel o
Programación por capas. En dichas arquitecturas a cada nivel se le confía una misión simple, lo que
permite el diseño de arquitecturas escalables (que pueden ampliarse con facilidad en caso de que las
necesidades aumenten).
El diseño más en boga actualmente es el diseño en tres niveles (o en tres capas).
Todas estas capas pueden residir en un único ordenador (no sería lo normal), si bien lo más usual es
que haya una multitud de ordenadores donde reside la capa de presentación (son los clientes de la
arquitectura cliente/servidor). Las capas de negocio y de datos pueden residir en el mismo
ordenador, y si el crecimiento de las necesidades lo aconseja se pueden separar en dos o mas
ordenadores. Así, si el tamaño o complejidad de la base de datos aumenta, se puede separar en
varios ordenadores los cuales recibirán las peticiones del ordenador en que resida la capa de
negocio.
Si por el contrario fuese la complejidad en la capa de negocio lo que obligase a la separación, esta
capa de negocio podría residir en uno o mas ordenadores que realizarían solicitudes a una única
base de datos. En sistemas muy complejos se llega a tener una serie de ordenadores sobre los
cuales corre la capa de datos, y otra serie de ordenadores sobre los cuales corre la base de datos.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Por estas razones, existe una fuerte y bien avanzada tendencia a adoptar una arquitectura de tres
capas.

Modelo Cuatro capas


Los desarrollos más recientes empiezan a experimentar con una capa adicional:
 Presentación;
 Aplicación;
 Dominio de la aplicación;
 Repositorio
La idea básica es separar todo lo que es programación GUI de la aplicación per se (y por ende tiende
a usar frameworks para GUI como MFC). El nivel de la presentación no hace cálculos, consultas o
actualizaciones sobre el dominio --de hecho nisiquiera tiene visibilidad sobre la capa del dominio. La
capa de la aplicación es la encargada de accesar la capa del dominio, simplificar la información del
dominio convirtiéndolo a los tipos de datos que entiende la interfaz: enteros, reales, cadenas de
caracteres, fecha y clases contenedoras (container, collection).
Una forma de organizar esta nueva capa de la aplicación es considerarla una fachada al dominio.
Cada aplicación presenta una fachada diferente (y simple) del dominio a la interfaz.

Diseño de componentes
Para que una solución sea considerada un patrón debe poseer ciertos componentes fundamentales:
• Nombre del patrón. Permite describir en pocas palabras un problema de diseño junto con sus
soluciones y consecuencias.
• Problema (o fuerzas no balanceadas). Indica cuándo aplicar el patrón. En algunas
oportunidades el problema incluye una serie de condiciones que deben darse para aplicar el
patrón. Muestra la verdadera esencia del problema. Este enunciado se completa con un
conjunto de fuerzas, término que se utiliza para indicar cualquier aspecto del problema que
deba ser considerado a la hora de resolverlo, entre ellos:
- Requerimientos a cumplir por la solución.
- Restricciones a considerar.
- Propiedades deseables que la solución debe tener.
Son las fuerzas las que ayudan a entender el problema dado que lo exponen desde distintos puntos
de vista.
• Solución. No describe una solución o implementación en concreto, sino que un patrón es más
bien como una plantilla que puede aplicarse en diversas situaciones diferentes. El patrón
brinda una descripción abstracta de un problema de diseño y cómo lo resuelve una
determinada disposición de objetos. Que la solución sea aplicable a diversas situaciones
denota el carácter “recurrente” de los patrones.
• Consecuencias. Resultados en términos de ventajas e inconvenientes.

Ver Video: Modelos de desarrollo, en la Unidad 6,


en el Módulo 5, en la plataforma elearning

Actividades

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 7. Desarrollo de Aplicaciones Eeb con
Struts
Objetivos
 Introducirse en el patrón MVC.
 Creación de proyectos basados en el patrón MVC con Struts.
 Desarrollar ejemplos con el Framework de Struts.

Introducción
Struts se basa en en el patrón de diseño MVC, en el patrón MVC el flujo de la aplicación está dirigido
por un Controlador central. El Controlador delega solicitudes HTTP a un manejador. Los
manejadores están unidos a un Modelo, y cada manejador actúa como un adaptador entre la
solicitud y el Modelo. En los desarrollos web el Modelo representará la lógica de negocio de la
aplicación. Luego el control normalmente es devuelto a través del Controlador hacia la Vista
apropiada. El reenvío puede determinarse consultando los conjuntos de mapeos, normalmente
cargados desde una base de datos o un fichero de configuración. Esto proporciona un acoplamiento
cercano entre la Vista y el Modelo, que puede hacer las aplicaciones significativamente más fáciles
de crear y de mantener.
Struts es un framework que implementa el patrón de arquitectura MVC en Java
Un framework es la extensión de un lenguaje mediante una o más jerarquías de clases que
implementan una funcionalidad y que pueden ser extendidas. El framework puede involucrar
TagLibraries.
El patrón de arquitectura MVC (Model-View-Controller) es un patrón que define la organización
independiente del Model (Objetos de Negocio), la View (interfaz con el usuario u otro sistema) y el
Controller.

Las aplicaciones Struts tiene tres componentes principales: un servlet controlador, que está
proporcionado por el propio Struts, páginas JSP (la "vista"), y la lógica de negocio de la aplicación (o
el "modelo"). Veamos como esto funciona todo junto.
El servlet controlador de Struts une solicitudes HTTP con otros objetos desarrollados por el
programador. Una vez inizializado, el controlador analiza un fichero de configuración de recursos, La
configuración de recursos define (entre otras cosas) los
org.apache.struts.action.ActionMapping para una aplicación. El controlador usa estos
mapeos para convertir las solicitudes HTTP en acciones de aplicación.
En el ActionMapping debemos inlcuir un path solicitado, el tipo objeto (subclase de Action) para
actuar sobre la solicitud, y otras propiedades según se necesite.
El objeto Action puede manejar la solicitud y responder al cliente, o indicar a que control debería
ser reenviado.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Marco de trabajo MVC
Componentes del modelo
Corresponden a la lógica del negocio con el cual se comunica la aplicación web. Usualmente el
modelo comprende accesos a Bases de Datos o sistemas que funcionan independientemente de la
aplicación web.

Componentes del control


Los componentes de control son los encargados de coordinar las actividades de la aplicación, que
van desde la recepción de datos del usuario, las verificaciones de forma y la selección de un
componente del modelo a ser llamado. Por su parte los componentes del modelo envían al control
sus eventuales resultados y/o errores de manera de poder continuar con otros pasos de la
aplicación.
Esta separación simplifica enormemente la escritura tanto de vistas como de componentes del
modelo: Las páginas JSP no tienen que incluir manejo de errores, mientras que los elementos del
control simplemente deciden sobre el paso siguiente a seguir.
Entre las características de Struts se pueden mencionar:
Configuración del control centralizada.
Interrelaciones entre Acciones y página u otras acciones se especifican por tablas XML en lugar de
codificarlas en los programas o páginas.
Componentes de aplicación, que son el mecanismo para compartir información bidireccionalmente
entre el usuario de la aplicación y las acciones del modelo.
Librerías de entidades para facilitar la mayoría de las operaciones que generalmente realizan las
páginas JSP.
Struts contiene herramientas para validación de campos de plantillas. bajo varios esquemas que van
desde validaciones locales en la página (en javaScript) hasta las validaciones de fondo hechas a
nivel de las acciones.
Struts permite que el desarrollador se concentre en el diseño de aplicaciones complejas como una
serie simple de componentes del Modelo y de la vista intercomunicados por un control centralizado.
Diseñando de esta manera se debe obtener una aplicación más consistente y más fácil de mantener.
Componentes de la vista
La parte de la Vista de una aplicación basada en Struts generalmente está construida usando
tecnología JavaServer Pages (JSP). Las págnas JSP pueden contener texto HTML estático (o XML)
llamado "plantilla de texto", además de la habilidad de insertar contenido dinámico basado en la
interpretación (en el momento de solicitud de la página) de etiquetas de acción especiales. El
entorno JSP incluye un conjunto de etiquetas estándard, como Además, hay una
facilidad estándard para definir nuestras propias etiquetas, que están organizadas en "librerías de
etiquetas personalizadas".
Struts incluye una extensa librería de etiquetas personalizadas que facilitan la creación de interfaces
de usuario que están completamente internacionalizados, y que interactúan amigablemente con
beans ActionForm que son parte del Modelo del sistema. El uso de estas etiquetas se explica más
adelante en detalle.
Además de las páginas JSP y la acción y las etiquetas personalizadas que contienen, normalmente
los objetos de negocio necesitan poder dibujarse a sí mismos en HTML (o XML), basándose en su
estado actual en el momento de la solicitud. La salida renderizada desde dichos objetos puede
incluirse fácilmente en una página JSP resultante usando la etiqueta de acción estándard

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Desarrollar una clase action de Struts
La clase Action define dos métodos que podrían ser ejecutados dependiendo de nuestro entorno
servlet:
public ActionForward perform(ActionMapping mapping,
ActionForm form,
ServletRequest request,
ServletResponse response)
throws IOException, ServletException;

public ActionForward perform(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException;
La mayoría de los proyectos sólo usarán la versión "HttpServletRequest".
El objetivo de una clase Action es procesar una solicitud, mediante su método perform(), y devolver
un objeto ActionForward que identifica dónde se debería reenviar el control (por ejemplo a una JSP)
para proporcionar la respuesta apropiada. En el patrón de diseño MVC/Model 2, una clase Action
típica implementará una lógica como ésta en su método perform():
Validar el estado actual de la sesión del usuario (por ejemplo, chequear que el usuario ha hecho el
login). Si la clase Action encuentra que no existe logon, la solicitud es reenviada a la página JSP que
muestra las peticiones del nombre de usuario y la password para logging on. Esto podría ocurrir
porque un usuario intente entrar "en el medio" de una aplicación (digamos, desde un bookmark), o
porque la sesión ha expirado, y el contenedor servlet creó una nueva.
Si la validación no se ha completado, valida las propiedades del bean formulario según sea
necesario. Si se encuentra un problema, almacena las claves de los mensajes de error apropiados
como un atributo de la petición, y reenvía el control de vuelta al formulario de entrada para que se
puedan corregir los errores.
Realizar el procesamiento requerido para tratar con esta solicitud (como grabar un fila de la base de
datos). Esto se puede hacer mediante código lógico embebido dentro de la propia clase Action, pero
generalmente debería realizarse llamando a un método apropiado del bean de lógica de negocio.
Actualizar los objetos del lado del servidor que serán usados para crear la siguiente página del
interface de usuario (normalmente beans del ámbio de solicitud o de sesion, dependiendo de cuánto
tiempo necesitemos mantener estos ítems disponibles).
Devolver un objeto ActionForward apropiado que identifica la página JSP usada para generar esta
respuesta, basada en los beans actualizados recientemente. Típicamente adquiriremos una
referencia a dicho objeto llamando a findForward() o al objeto ActionMapping que recibimos (si
estamos usando un nombre lógico normal para este mapeo), o en el propio servlet controlador (si
estamos usando un nombre lógico global para la aplicación).
Entre los problemas de diseño a recordar cuando codificamos clases Action incluimos los siguientes:
El servlet controlador crea un sólo ejemplar de nuestra clase Action, y la usa para todas las
solicitudes. Es decir, necesitamos codificar nuestra clase Action para que opere correctamente en un
entorno multi-thread, como si estuvieramos codificando un método service() de un servlet.
El principio más importante que nos ayuda en la codificación de threads seguros es usar sólo
variables locales, no variables de ejemplar, en nuestra clase Action. Las variables locales se crean
en una pila que es asignada (por nuestra JVM) a cada thread solicitado, por eso no necesitamos
preocuparnos de compartirlas.
Los beans que representan el Modelo de nuestro sistema podría lanzar excepciones debido a
problemas de acceso a bases de datos o a otros recursos. Deberíamos atrapar dichas excpeciones

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
en la lógica de nuestro método perform(), y guardalas en el fichero de log de la aplicación (junto con
el seguimiento de pila correspondiente) llamando a:
servlet.log("Error message text", exception);
Como regla general, asignar recursos y mantenerlos a través de las solicitudes del mismo usuario
(en la misma sesión de usuario) puede causar problemas de escalabilidad. Deberíamos pensar en
liberar esos recursos (como las conexions a una base de datos) antes de reenviar el control al
componente de la Vista apropiado -- incluso si un método del bean que hemos llamado lanza una
excepción.
Además, queremos protegernos contra clases Action que son demasiado largas. La forma más fácil
de hacer que esto suceda es embeber la lógica funcional en la propia clase Action, en vez codificarla
en beans de lógica de negocio independientes. Además de hacer la propia clase Action dura de
entender y de mantener, esta aproximación también hace díficil re-utilizar el código de la lógica de
negocio, porque está embebido dentro de un componente (la clase Action) que está concebido para
ser ejecutado en un entorno de aplicación Web.
Una Action puede dividirse en varios métodos locales, mientras que todas las propiedades
necesarias sean pasadas en las firmas de métodos. La JVM maneja dichas propiedades usando la
pila, y por eso son seguras ante los threads.
La aplicación de ejemplo incluida con Struts no cumple este principio, porque la propia lógica de
negocio está embebida dentro de las clases Action. Esto debería considerarse un bug en el diseño de
la aplicación de ejemplo, en vez de una característica intrínseca de la arquitectura , o una
aproximación a emular.

Clase Action creada con NetBeans en un proyecto Struts:

ActionMapping
Para poder operar satisfactoriamente, el servlet controlador Struts necesita conocer varias cosas
sobre como se debería mapear toda URI solicitada a una clase Action apropiada. El conocimiento
requerido ha sido encapsulado en un interface Java, llamado ActionMapping, estas son las
propiedades más importantes:
 type - nombre totalmente cualificado de la clase Java que implementa la clase Action usada
por este mapeo.
 name - El nombre del bean de formulario definido en el fichero de configuración que usará
este action.
 path - El path de la URI solicitada que corresponden con la selección de este mapeo.
 unknown - Seleccionado a true si este action debería ser configurado como por defecto para
esta aplicación, para manejar todas las solicitudes no manejadas por otros action. Sólo un
Action puede estar definido como por defecto dentro de una sóla aplicación.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
 validate - Seleccionado a true si se debería llamar al método validate() de la action asociada
con este mapeo.
 forward - El path de la URI solicitada a la que se pasa el control cuando se ha invocado su
mapeo. Esto es una alternativa a declarar una propiedad type.

Fichero de Configuración de los Mapeos de Action


Sería posible escribir una pequeña clase Java que simplemente ejemplarizara nuevos ejemplares de
ActionMapping, y llamara a todos los métodos set() apropiados. Para hacer este proceso más
sencillo, Struts incluye un módulo Digester que es capaz de leer la descripción basada en XML de los
mapeos deseados, creando los objetos apropiados de la misma forma. Puedes encontrar más
información sobre este Digester en la documentación del API
La responsabilidad del desarrollador es crear un fichero XML llamado struts-config.xml, y situarlo en
el directorio WEB-INF de su aplicación. Este formato de documento está restringido por su definición
en "struts-config_1_0.dtd". El elemento XML más exterior debe ser
Dentro del elemento hay dos elementos importantes que son usados para describir
nuestras acciones:

Esta sección contiene nuestras definiciones de beans. Usamos un elemento por cada
bean de formulario, que tiene los siguientes atributos importantes:
name: Un identificador único para este bean, que será usado para referenciarlo en los
correspondientes mapeos de acciones. Normalmente, es también el nombre del atributo de solicitud
o sesión bajo el que se almacena este bean de formulario.
type: El nombre totalmente cualificado de la clase Java de nuestro bean de formulario.

Esta sección contiene nuestras definiciones de acciones. Usamos un elemento por cada una
de nuestras acciones que queramos definir. Cada elemento action requiere que se definan los
siguientes atributos:
path: El path a la clase action en relación al contexto de la aplicación.
type: El nombre totalmente cualificado de la clase Java de nuestra clase Action.
name: El nombre de nuestro elemento para usar con esta action.
El fichero struts-config.xml de la aplicación de ejemplo incluye las siguientes entradas de mapeo
para la función "log on", que se usará para ilustrar los requerimientos. Podemos apreciar que las
entradas para otras acciones se han dejado fuera:
<struts-config>
<form-beans>
<form-bean
name="FormularioLogin"
type="org.apache.struts.example.FormularioLogin" />
</form-beans>
<global-forwards
type="org.apache.struts.action.ActionForward" />
<forward name="login" path="/login.jsp"
redirect="false" />
</global-forwards>
<action-mappings>
<action
path="/logon"
type="org.apache.struts.example.ActionLogin"
name="FormularioLogin"
scope="request"
input="/login.jsp"

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
unknown="false"
validate="true" />
</action-mappings>
</struts-config>
Primero se define el bean formulario, Un bean básico de la clase
"org.apache.struts.example.FormularioLogin" es mapeado al nombre lógico "FormularioLogin". Este
nombre se usa como un nombre de atributo de sesión o solicitud para el bean de formulario.
La sección "global-forwards" se usa para crear mapeos de nombres lógicos para páginas JSP usadas
comunmente. Cada uno de estos reenvíos está disponible a través de una llamada a nuestro
ejemplar de mapeo de action, por ejemplo actionMappingInstace.findForward("envio").
Como podemos ver, este mapeo corresponde con el path /logon (realmente, porque la aplicación de
ejemplo usa mapeo de extensión, la URI que especificamos en una página JSP terminaría en
/logon.do). Cuando se recibe una solicitud que corresponde con el path, se crea un ejemplar de
ActionLogin (sólo la primera vez). El Servlet controlador buscará un bean de ámbito de sesión bajo
la clave FormularioLogin, creando y guardando un bean de la clase especificada si es necesario.
Opcionales pero muy útiles son los elementos localizados en "forward". En la aplicación de ejemplo,
muchas acciones incluyen un reenvio local "success" y/o "failure" como parte de un mapeo de
Action.
<action path="/editSubscription"
type="org.apache.struts.example.Actionrecogida"
name="RecogidaForm"
scope="request"
validate="false">
<forward name="failure" path="/Menu.jsp"/>
<forward name="success" path="/Recogida.jsp"/>
</action>
Usando estas dos propiedades extras, las clases Action de la aplicación de ejemplo son casi
totalmente independientes de los nombres reales de las páginas JSP que son usadas por los
diseñadores, Las páginas, pueden renombrarse (por ejemplo) durante un rediseño, con un mínimo
impacto en las propias clases Action. Si los nombres de las páginas JSP "next" estuvieran codificados
dentro de las clases Action, todas estas clases tendrían que ser modificadas. Por supuesto, podemos
definir cualquier propiedad de reenvío local que tenga sentido para nuestra aplicación.
Una sección más de buen uso es la sección que especifica las fuentes de datos que
puede usar nuestra aplicación. Aquí podemos ver cómo especificar una fuente de datos para nuestra
aplicación dentro de struts-config.xml:
<struts-config>
<data-sources>
<data-source
autoCommit="false"
description="Ejemplo de conexión"
driverClass="org.postgresql.Driver"
maxCount="4"
minCount="2"
password="passwordeconexion"
url="jdbc:postgresql://localhost/BDEjemplos"
user="nombreusuario"/>
</data-sources>
</struts-config>

Plantilla Struts-config creada con NetBeans en un proyecto Struts:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
En este ejercicio desarrollaremos un ejemplo web donde utilicemos la clase action y el método
Action Forward.
Cargaremos en la página Visitas.jsp en un combo la información devuelta de un HashTable.
Al seleccionar un elemento el Combo y rellenar las observaciones realizaremos un submit que nos
enviará a resultadocorrecto.jsp.
Visitas.jsp

Resultadocorrecto.jsp

VISTA: Visitas.jsp

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>


<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
<head>
<title></title>
</head>

<body>
<center>
<h2></h2>
<hr width='60%'>

<html:form action='/InsertaVisistas'>
<table border="0">
<tr>

<td>Pais</td><td>
<html:select property="pais" >
<html:options collection="tablapaises" property="key" labelProperty="value" />

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</html:select>

</td>
</tr>
<tr>
<td>
Observaciones</td><td> <html:textarea property="observaciones" cols="50" rows="3" />
</td><td></td>
</tr>
<tr><td> <html:submit value="Enviar"/></td> </tr>

</table>
</html:form>

<br/>
</center>
</body>
</html>

VISTA: resultadocorrecto.jsp

<%@page contentType="text/html"%>
<html>
<head><title>JSP Page</title></head>
<body>

<h2>La acción se ejecutó satisfactoriamente</h2>

</body>
</html>

CONTROLADOR: InsertaVisitasAction
package webstruts;

import org.apache.struts.action.*;
import javax.servlet.http.*;
import java.util.*;

public class InsertaVisitasAction extends Action implements org.apache.struts.action.PlugIn {

public ActionForward execute(ActionMapping actionMapping,ActionForm actionForm,


HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {

ActionForward retValue = null;


try // ejecutamos la funcion de negocio
{
// Obtenemos acceso al formulario
DynaActionForm formulario = (DynaActionForm) actionForm;

// aqui va la inserción de los datos


System.out.println("El pais es: " + formulario.get("pais"));
System.out.println("Observaciones: " + formulario.get("observaciones"));

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
// redirigimos a la presentación
retValue = actionMapping.findForward("correcto");
}
catch(Exception e) // en caso de problemas retornar a la página origen
{
// recuperamos acceso al JSP de origen
retValue = actionMapping.getInputForward();

return retValue; // redirigimos a la presentacion


}

/*
* Los métodos destroy e init son obligatorios al implementar el interfaz PlugIn
*/
public void destroy() {
}

public void init(org.apache.struts.action.ActionServlet actionServlet,


org.apache.struts.config.ModuleConfig moduleConfig) throws javax.servlet.ServletException {

Hashtable vPaises = new Hashtable();

// aqui hay que poner el código que nos proporcione los datos de la base de datos
vPaises.put("1","España");
vPaises.put("2","Francia");
vPaises.put("3","Inglaterra");
vPaises.put("4","Italia");

// ponemos la tabla en el ambito de la aplicación


actionServlet.getServletContext().setAttribute("tablapaises",vPaises);
}
}

ARCHIVO CONFIGURACIÓN: struts-config.xml


<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" _
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>

<form-beans>
<form-bean
name="VisitasForm"
type="org.apache.struts.action.DynaActionForm">
<form-property name="pais" type="java.lang.Integer"/>
<form-property name="observaciones" type="java.lang.String"/>
</form-bean>
</form-beans>

<global-exceptions>
</global-exceptions>

<global-forwards>
<forward name="correcto" path="/resultadocorrecto.jsp"/>
</global-forwards>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<action-mappings>

<action path="/InsertaVisistas"
type="webstruts.InsertaVisitasAction"
name="VisitasForm"
scope="request"
validate="true"
input="/Visitas.jsp"/>
</action-mappings>

<controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/>
<message-resources parameter="com/myapp/struts/ApplicationResource"/>
<plug-in className="org.apache.struts.tiles.TilesPlugin" >

<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />

<set-property property="moduleAware" value="true" />


</plug-in>

<plug-in className="webstruts.InsertaVisitasAction" >


</plug-in>

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>

</struts-config>

Ver Video: Creación de un proyecto Struts, en la Unidad 7,


en el Módulo 5, en la plataforma elearning

Laboratorio: Creación de propiedades en el archivo


ApplicationResource.
Objetivo
Creación de un proyecto Struts y uso del archivo ApplicationResource.
Enunciado
Crear una página jsp que muestre mensajes de bienvenida a nuestra tienda virtual.
Mostraremos los mensajes personalizándolos en el archivo applicationResource.properties.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
TiendaStruts.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>


<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>

<html>
<body bgcolor="Blue">
<form>
<div style="left: 210px; top: 10px; font-size: 24px;
font-weight: bold; position: absolute">
<bean:message key="literal.bienvenida" />
</div>
<div style="left: 250px; top: 40px; font-size: 12px; position: absolute">
*<bean:message key="literal.mensajeEnvios" />
</div>
<form>
</body>
</html>

Applicationresource.properties
literal.bienvenida=Bienvenido a la tienda oficial
literal.mensajeEnvios=Selecciona si tu envío es dentro de España o Internacional

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 8. Desarrollo de Aplicaciones Web
con Administración de Sesiones
Objetivos
 Realizar desarrollos web Accediendo a una sesión y Asociando objetos con una sesión.
 Comprender la importancia de las Cookies en el desarrollo de una aplicación web.

Introducción
En muchos desarrollos las aplicaciones necesitan que una serie de solicitudes de un cliente sean
asociadas con otro. Por ejemplo, una aplicación de compra de productos guarda el estado de un
carrito de compras de un usuario a través de las solicitudes. Las aplicaciones basadas en Web son
responsables por mantener este estado, llamado sesión, ya que HTTP no tiene estado. Para soportar
las aplicaciones que necesitan mantener el estado, la tecnología Servlet de Java proporciona una API
para manejo de sesiones y permite varios mecanismos para implementar sesiones.
El API de los servlets nos da un modelo para guardar información sobre una sesión. Una sesión
consiste en todas las peticiones (request) hechas durante una invocación desde un navegador. En
otras palabras, una sesión comienza cuando se abre el navegador y termina cuando este se cierra.
El primer problema con el que nos encontramos es identificar a cada cliente que se conecta. Esto se
soluciona asignando un identificador a cada cliente cada vez que este hace una petición a través de
http. Se podría pensar como identificador en la dirección IP de cada navegador, pero esto no es
posible porque puede haber varios clientes usando el mismo navegador, y por tanto, con la misma
dirección IP. Lo que usaremos son las llamadas cookies o una técnica conocida como la reescritura
del URL.
La clase HttpSession:
Métodos de esta clase:
 getCreationTime(): Devuelve el tiempo en que la sesión fue creada.
 getId(): Devuelve el identificador de la sesión.
 getLastAccessedTime(): Devuelve la última vez que el cliente hizo una petición para esta
sesión.
 getMaxInactiveInterval(): Devuelve la máxima cantidad de tiempo en el que la sesión se
mantiene en el motor del servlet.
 getValue(String): Devuelve el valor del objeto asociado al campo que se le pasa por
parámetro.
 getValueNames(): Devuelve un array de los datos de la sesión.
 invalidate(): invalida la sesión y la borra del contexto de la sesión.
 isNew(): Devuelve true si el contexto ha sido creado por el Server pero no ha sido usado por
el cliente.
 putValue(String, Object): Pone el dato objeto en el campo de nombre String.
 removeValue(String): Borra el campo del array de datos de la sesión.
 setMaxInactiveInterval(int): pone un tiempo límite que una sesión puede estar inactiva antes
de que el motor de servlets la elimine.
Hay tres aspectos del manejo de datos que deben de estar muy claros: el intercambio de sesiones,
la relocalización de sesiones y la persistencia de las sesiones.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Intercambio de sesiones (session swapping): Todos los servidores de servelts tienen una cantidad
limitada de recursos para la información de la sesión. En un esfuerzo por mantener el consumo de
estos recursos bajo control, la mayoría de los servidores de servlet tendrán un número máximo de
sesiones concurrentes en un mismo tiempo. Del mismo modo, tendremos un tiempo máximo de
espera, de forma que cuando una sesión permanece inactiva durante demasiado tiempo dentro de
un servidor, esa sesión será sustituída por otra. Esto sólo se podrá hacer si todos los objetos (datos)
de la sesión son serializables (implementan la interfaz java.io.Serializable). Si la sesión no es
serializable deberemos tenerla en memoria hasta que salga por sí sola.
Relocalización de las sesiones (session relocation): No hay ningún convenio que diga que un servlet
requerido sea servido por la misma JVM (Java Virtual Machine) o ni siquiera por el mismo servidor
físico. Un servidor debe de enviar el servlet lo más rápido posible. Por eso, para trabajar con datos
almacenados dentro de una sesión, el objeto sesión debe de ser relocalizable. De nuevo, esto
conlleva que los datos (objetos) almacenados en la sesión deben de ser serializables. Si los datos de
la sesión son serializables será fácil moverlos de una JVM a otra.
Persistencia de las sesiones (session persistence): Los servidores WEB deben de estar activados 24
horas al día, 7 días a la semana. Sin embargo, de vez en cuando es necesario tumbar los servidores
para su mantenimiento. De nuevo, la serialización nos va a salvar el día. El servidor de servlets
serializará todas las sesiones y las volcará en un disco auxiliar. Cuando la limpieza del servidor esté
completada, se recuperarán las sesiones sin que el usuario note el cambio.

El protocolo HTTP no permite almacenar estados. Para que una aplicación web sea efectiva, es
necesario que las peticiones de un cliente particular, sean asociadas con otras. Existen muchas
estrategias para el seguimiento de sesiones, han evolucionado con el tiempo, pero son difíciles o
problemáticas si se usan directamente. Esta especificación define una la interfaz HttpSession para
este cometido.
Mecanismos
Cookies. Podemos usar cookies HTTP para almacenar información sobre una sesión de compra, y
cada conexión subsecuente puede buscar la sesión actual y luego extraer la información sobre esa
sesión desde una localización en la máquina del servidor. Esta es una excelente alternativa, y es la
aproximación más ampliamente utilizada. Sin embargo, aunque los servlets tienen un Interface de
alto nivel para usar cookies, existen unos tediosos detalles que necesitan ser controlados:
- Extraer el cookie que almacena el identificador de sesión desde los otros cookies (puede
haber muchos, después de todo),
- Seleccionar un tiempo de expiración apropiado para el cookie (las sesiones interrumpidas
durante 24 horas probablemente deberían ser reseteadas), y
- Asociar la información en el servidor con el identificador de sesión (podría haber demasiada
información que se almacena en el cookie, pero los datos sensibles como los números de las
tarjetas de crédito nunca deben ir en cookies).
Reescribir la URL. Podemos añadir alguna información extra al final de cada URL que identifique la
sesión, y el servidor puede asociar ese identificador de sesión con los datos que ha almacenado
sobre la sesión. Esta también es una excelente solución, e incluso tiene la ventaja que funciona con
navegadores que no soportan cookies o cuando el usuario las ha desactivado. Sin embargo, tiene
casi los mismos problemas que los cookies, a saber, que los programas del lado del servidor tienen
mucho proceso que hacer, pero tedioso. Además tenemos que ser muy cuidadosos con que cada
URL que le devolvamos al usuario tiene añadida la información extra. Y si el usuario deja la sesión y
vuelve mediante un bookmark o un enlace, la información de sesión puede perderse.
Campos de formulario ocultos. Los formularios HTML tienen una entrada que se parece a esto:

Esto significa que, cuando el formulario se envíe, el nombre y el valor especificado se incluirán en
los datos GET o POST. Esto puede usarse para almacenar información sobre la sesión. Sin embargo,

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
tiene la mayor desventaja en que sólo funciona si cada página se genera dinámicamente, ya que el
punto negro es que cada sesión tiene un único identificador.
Los servlets proporcionan una solución técnica. Al API HttpSession. Este es un interface de alto nivel
construido sobre las cookies y la reescritura de URL. De hecho, muchos servidores, usan cookies si
el navegador las soporta, pero automáticamente se convierten a reescritura de URL cuando las
cookies no son soportadas o están desactivadas. Pero el autor de servlets no necesita molestarse
con muchos detalles, no tiene que manipular explícitamente las cookies o la información añadida a
la URL, y se les da automáticamente un lugar conveniente para almacenar los datos asociados con
cada sesión.
Creación de una sesión
Una sesión se considera nueva sólo cuando es prospectiva o no ha sido establecida. Debido a que
HTTP es un protocolo basado en petición-respuesta, una sesión no se considera nueva hasta que el
cliente se “une” a ella. Esto ocurre cuando la información de seguimiento de la sesión, es devuelta al
servidor, indicando que la sesión ha sido establecida. Mientras que esto no suceda, no se puede
asumir que la siguiente petición del cliente sea reconocida como parte de una sesión.
Ámbito de sesión
El objeto HttpSession tiene ámbito de aplicación (o servlet context). El mecanismo subyacente,
como por ejemplo la cookie que se utiliza para establecer una sesión, puede ser la misma o
diferente para distintos contextos, pero los objetos referenciados (incluyendo sus atributos), nunca
deben ser compartidos por el contenedor de servlets entre diferentes contextos.
Asociar atributos a una sesión
Un servlet puede añadir un atributo a una HttpSession mediante el nombre. Cualquier objeto
añadido a la sesión, estará disponible para otro servlet que tenga el mismo ServletContext y maneje
una petición identificada al principio como parte de la misma sesión.
Algunos objetos pueden requerir notificación cuando ellos son añadidos o removidos desde una
sesión. Esta información puede ser obtenida si el objeto implementa la interfaz
HttpSessionBindingListener. Esta interfaz define los siguientes métodos:
- valueBound: se debe llamar antes de que el objeto esté disponible a través del método
getAttribute de la interfaz HttpSession
- valueUnbound: se debe llamar después de que el objeto no esté disponible a través del
método getAttribute de la internas HttpSession.
Últimos accesos
El método getLastAccessedTime de la interfaz HttpSession permite a un servlet determinar el último
acceso a la sesión, antes de la actual petición. Se considera que ha habido un acceso a la sesión,
cuando el contenedor de servlets maneja primero la petición que es parte de la sesión.

Desarrollar servlets utilizando la administración de


sesiones
Cada sesión tiene un tiempo de espera para la caducidad de la sesión, a este tiempo de espera
podemos acceder en tiempo de ejecución con los métodos MaxInactiveInterval.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Otra posibilidad que nos permite un proyecto servlet es modificar el tiempo de espera en el archivo
de configuración XML, en el web.xml.

Podemos invalidar una sesión en tiempo de ejecución utilizando el método invalidate del objeto
session.
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class EjServlet extends HttpServlet {


protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession sesion=request.getSession();
sesion.invalidate();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}

Creación de un ejemplo con variables sesión


getAttribute(“nombre_variable”): Devuelve una instancia de Object en caso de que la sesión ya
tenga algo asociado a la etiqueta
nombre_variable null en caso de que no se haya asociado nada aún.
setAttribute(“nombre_variable”, referencia ):Coloca el objeto referenciado por referencia en la
sesión del usuario bajo el nombre nombre_variable. A partir de este momento, el objeto puede ser
recuperado por este mismo usuario en sucesivas peticiones. Si el objeto ya existiera, lo sobrescribe.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
getAttributesNames():Retorna una Enumeration con los nombres de todos los atributos establecidos
en la sesión del usuario.
1. Abriremos un proyecto web con NetBeans o el IDE que estemos utilizando y crearemos dos
ficheros servlet.

2. Insertar en el primer fichero servlet el siguiente código:


import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class EjServlet extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)


throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
HttpSession sesion = request.getSession();
sesion.setAttribute("nombre", "Pepe" );
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Servlet2</title>");
out.println("</head>");
out.println("<body>");
out.println("<a href='Servlet2'>Llamar Servlet2</a>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
}
Creamos un objeto HttpSession(HttpSession sesion = request.getSession();) y asignamos un valor a
una variable session con el método setAttribute(sesion.setAttribute("nombre", "Pepe" );)

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
3. Insertar en el segundo fichero servlet el siguiente código:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class Servlet2 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)


throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
HttpSession sesion = request.getSession(false);
//false por ser acceso de lectura
String NombreCliente = (String)sesion.getAttribute( "nombre" );
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Servlet2</title>");
out.println("</head>");
out.println("<body>");
out.println("HOLA:"+NombreCliente);
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
}
Creamos un objeto HttpSession(HttpSession sesion = request.getSession(false);) y recuperamos el
valor de la variable session con el método getAttribute(sesion.getAttribute("nombre”);)

Describir la implementación de cookies de la


administración de sesiones.
Cuando un usuario accede a nuestro sitio y queremos asociarle una sesión una de las formas más
habituales es manteniendo el identificador en el cliente como una cookie.
Si su aplicación utiliza objetos de sesión debe asegurarse que el seguimiento de sesión está
habilitado reescribiendo las URL cuando el cliente desactiva las cookies. El método encodeURL(URL)
incluye el identificador de sesión en la URL solo si las cookies están deshabilitadas; de otra forma
este retorna la URL sin cambios.

Ejemplo de uso de cookies


1. Crearemos una página html en un proyecto queb que incorpore dos cajas de texto para
introducir usuario y contraseña.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
PÁGINA HTML
<html>

<head>
<title>RESPUESTA</title>
</head>

<body TEXT=#FFFFFF BGCOLOR=#000080">


<center>
<form METHOD="POST" ACTION="ServletCookies">
<br><br><br>
<table>
<tr>
<td><b>USUARIO</b><TD>
<TD><input type=TEXT name=user></td>
</tr>
<tr>
<td><b>CONTRASEÑA</b><TD>
<TD><input type=password name=key></td>
</tr>
<tr>
<td><input type=submit value=Enviar></td>
<td><input type=reset value=Cancelar></td>
</tr>

</table>

</form>

</center>
</body>

</html>
2. Solicitaremos un Servlet que se encargará de guardar en una Cookie el valor de los datos
introducidos en las cajas de texto.
Si es la primera vez que solicita el Sevlet, mostraremos un mensaje dando las gracias por
registrarse en nuestro sitio, si por el contrario ya se han creado las Cookies, mostraremos un
mensaje de bienvenida al sitio.
SERVLET
Si no ha creado la Cookie:

Si ha creado la Cookie:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletCookies extends HttpServlet{


static Cookie [] galletas;

public void doPost (HttpServletRequest peticion, HttpServletResponse respuesta) throws


IOException, ServletException{

boolean nuevo = true;


String usuario = peticion.getParameter ("user");
String contra = peticion.getParameter ("key");

galletas = peticion.getCookies();
if (galletas!=null){
for(int i=0; i<galletas.length; i++){
if(galletas[i].getName().equals(usuario) &&
galletas[i].getValue().equals(contra)){
nuevo=false;
break;
}
}
}
ServletOutputStream flujo = respuesta.getOutputStream ();
respuesta.setContentType("text/html");
Cookie galleta = new Cookie (usuario, contra);
galleta.setMaxAge(30);
respuesta.addCookie(galleta);

flujo.println("<html>");
flujo.println("<head><title>RESPUESTA</TITLE></HEAD>");
flujo.println("<BODY TEXT=#FFFFFF BGCOLOR=#000080><CENTER><H1>");
if (nuevo){
flujo.println("GRACIA POR REGISTRARSE CON NOSOTROS");
}else{
flujo.println("BIENVENIDO A TU SITIO FAVORITO");
}
flujo.println("</H1></CENTER></BODY></HTML>");
flujo.close();

}
}

Ver Video: Variables Session, en la Unidad 8,


en el Módulo 5, en la plataforma elearning

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Laboratorio: Creación y uso de Cookies.
Objetivos
Coprender el funcionamiento y tratamiento de la Cookies en Java.
Enunciado
- Crear una página en la que podamos crear cookies para capturar las aficiones de un usuario.
- Si es la primera vez que el usuario entra en nuestra página le redireccionaremos hacia la
página de creación de Cookies para que nos describa sus gustos.
- Una vez que el usuario haya rellenado los datos, crearemos las Cookies correspondientes y el
usuario podrá entrar en nuestra página tantas veces como desee, escribiendo los valores que
el usuario haya seleccionado.

SOLUCIÓN
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.http.*;

public class EjercicioCookie extends HttpServlet {


static Cookie[] cooks;
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

String pedirDatos = "<html><head><title>Bienvenido</title></head><body>" +


"<center> <form METHOD=POST ACTION=EjercicioCookie><table border=1><tr>" +
"<td><b>Nombre del usuario:</b><td></tr>" +
"<tr><td><input type=TEXT name=usuario></td></tr></table><br><br>" +
"<table border=1><tr>" +
"<td><b>Aficiones:</b><td></tr>" +
"<tr><td>Lectura: <input type=radio name=aficiones value=lectura><br>" +
"Viajes: <input type=radio name=aficiones value=viajes></td></tr></table>" +
"<table border=1><tr>" +
"<td><b>Color:</b><td></tr>" +

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
"<tr><td>Rojo: <input type=radio name=color value=rojo><br>" +
"Azul: <input type=radio name=color value=azul></td></tr></table><br>" +
"<input type=submit value=Enviar>" +
"</form></center></body></html>";
try {

cooks = request.getCookies();
if (cooks==null){
out.println(pedirDatos);
Cookie cook = new Cookie("alta", "s");
cook.setMaxAge(60);
response.addCookie(cook);
}
else{
String usuario = "";
String aficion = "";
String color = "";
int visitas = 0;
String fecha ="";
boolean nuevo = true;
for(int i=0; i<cooks.length; i++){
if(cooks[i].getName().equals("nombre")){
usuario = cooks[i].getValue();
nuevo = false;
}
if(cooks[i].getName().equals("aficion")){
aficion = cooks[i].getValue();
}
if(cooks[i].getName().equals("colorFav")){
color = cooks[i].getValue();
}
if(cooks[i].getName().equals("visitas")){
visitas = Integer.parseInt(cooks[i].getValue()) + 1;
}
if(cooks[i].getName().equals("fecha")){
fecha = cooks[i].getValue();
}
}
if(nuevo){
usuario = request.getParameter("usuario");
aficion = request.getParameter("aficiones");
color = request.getParameter("color");
visitas = 1;
}
Cookie cook = new Cookie("nombre",usuario);
cook.setMaxAge(30);
response.addCookie(cook);

cook = new Cookie("aficion", aficion);


cook.setMaxAge(30);
response.addCookie(cook);
cook = new Cookie("colorFav", color);
cook.setMaxAge(30);
response.addCookie(cook);

cook = new Cookie("visitas", String.valueOf(visitas));


cook.setMaxAge(30);

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
response.addCookie(cook);

java.util.Date dia = new java.util.Date();


java.text.DateFormat formato = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);

cook = new Cookie("fecha", formato.format(dia));


cook.setMaxAge(30);
response.addCookie(cook);

out.println("<html>");
out.println("<head>");
out.println("<title>Hola otra vez</title>");
out.println("</head>");
out.println("<body><center>");
String colSal;
if (color.equals("rojo")) colSal = "#FF0000";
else colSal = "#0000FF";
out.println("<table border=1 bgcolor=" + colSal +">");
out.println("<tr><td><b>Bienvenido</b></td></tr");
out.println("<tr><td>Esta es su visita: "+ visitas +"</td></tr");
out.println("<tr><td>Última visita: "+ fecha +"</td></tr");
if (aficion.equals("lectura"))
out.println("<tr><td><img src=http://localhost:8084/ServletsVariados/russell.jpg" +
"></td></tr");
else
out.println("<tr><td><img src='http://localhost:8084/ServletsVariados/tycho.jpg'" +
"></td></tr");
out.println("</table>");
out.println("</center></body>");
out.println("</html>");
}
}
catch(Exception e){

} finally {
out.close();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 9. Uso de Filtros en Aplicaciones Web
Objetivos
 Programar el filtro
 Programar las solicitudes y respuestas a medida
 Especificando la cadena de filtros para cada recurso Web

Introducción
Un filtro es una clase que tiene como tarea trabajar con una solicitud como lo hace un servlet, pero
debe permitir la gestión de la solicitud para seguir con otros filtros o servlets. Un filtro puede realizar
una tarea auxiliar como, por ejemplo el inicio de sesión, la realización de comprobaciones de
autenticación especializadas o la anotación de la solicitud o de los objetos de respuesta antes de
ejecutar el servlet.
Los filtros son objetos Java que pueden añadir funcionalidad a los servlets (u otros artefactos web)
interceptando las peticiones y las respuestas.
Es una implementación del patrón de diseño Decorador.
Permiten gestionar el control de acceso, registros (logs), transformar contenido, mantener una
caché de páginas dinámicas, etc.
Pueden encadenarse y formar una cadena de filtros.
Se configuran en web.xml
Los filtros son objetos que permiten modificar un encabezado y contexto en una solicitud o
respuesta.

Los filtros no son capaces de crear una respuesta por si mismos, lo que le diferencia es que puede
ser utilizada en cualquier tipo de recurso web.
Las principales tareas que un filtro puede realizar son las siguientes:
 Modificar los encabezados y los datos de la solicitud.
 Modificar los encabezados y datos de la respuesta. Puede hacer para proveer una versión a
medida de la respuesta.
 Consultar la solicitud y actuar de acuerdo a esta.
 Bloquear la solicitud y respuesta de seguir ejecutando.
 Interactuar con recursos externos.
 Encapsular tareas comunes en unidades reutilizables.
 Realizar labores de autentificación y bloqueo de peticiones.
 Realizar estadísticas de impactos al Sitio Web.
 Formatear los datos enviados al usuario

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
los datos enviados como respuesta al usuario pueden ser transformados al pasar por un Filtro de
salida. En este caso los Filtros pueden comprimir la información, manipular imágenes para
sobreponer en ellas un texto o logo representativo de nuesto sitio Web
La versión 2.3 de la especifiación de los Servlets introduce los Filtros como un medio flexible de
interactuar con peticiones y respuestas HTTP antes y después de que el Contenedor Web llame a los
recursos Web. Estos recursos Web pueden ser tanto estáticos como dinámicos:
 recursos Web estáticos:
páginas HTML e imágenes
 recursos Web dinámicos:
Servlets y páginas JSP
Los Filtros son una especie de Servlets que interceptan dinámicamente peticiones y respuestas y
pueden manipular la información contenida en ellas.
Son clases Java que pueden interceptar y manipular las peticiones de un Navegador antes de que el
Contenedor Web las pueda ejecutar.

Programando los filtros


Una clase realizada con java que use filtros debe implementar la interface javax.servlet.Filter y
usará el método doFilter().

Métodos de la clase Filter


Métodos
void destroy ()
Este método es llamado por el contenedor web para indicar a un filtro que se
está fuera de servicio.
void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain)
El método doFilter es llamado por el contenedor cada vez que una solicitud es
aprobada a través de la cadena debido a una petición del cliente para un recurso
en el extremo de la cadena.
void init ( FilterConfig filterConfig)
Este método es llamado por el contenedor web para indicar a un filtro que se
está poniendo en servicio.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
En el siguiente ejemplo se indica una sencilla implementación de filtro que registra un mensaje y
transmite el control a la cadena, que puede incluir otros filtros o un servlet, tal como describe el
descriptor de implementación:
Package ejemplo;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FiltroLog implements Filter {


private FilterConfig filterConfig;
private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());

public void doFilter(HttpServletRequest request,


HttpServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
log.info("Filtro procesado " +
getServletConfig().getInitParameter("logType") +
" petición ");

filterConfig.doFilter(request, response);
}

public FilterConfig getFilterConfig() {


return filterConfig;
}
public void setFilterConfig(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
}
Al igual que los servlets, un filtro se configura en el descriptor de implementación a través de la
declaración del filtro con el elemento y, a continuación, a través de su asignación a un patrón
de URL con el elemento También puedes dar valor a los filtros a otros servlets de
forma directa.
El elemento tiene un elemento , un elemento y el elemento opcional

<filter>
<filter-name>logSpecial</filter-name>
<filter-class>ejemplo.FiltroLog</filter-class>
<init-param>
<param-name>logType</param-name>
<param-value>special</param-value>
</init-param>
</filter>
El elemento contiene un elemento que se corresponde con el nombre de
un filtro declarado y también un elemento

para aplicar el filtro a las URL o un elemento que se corresponde con el


nombre de un servlet declarado y que permite aplicar el filtro siempre que se ejecute el servlet.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<filter-mapping>
<filter-name>logSpecial</filter-name>
<url-pattern>*.special</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>logSpecial</filter-name>
<servlet-name>comingsoon</servlet-name>
</filter-mapping>

javax.servlet.FilterConfig

El contenedor de servlets provee una implementación para esta interface. Al igual que ServletConfig,
la instancia se pasa a través del método init(FilterConfig). Esta interface provee métodos para
acceder a los parámetros de inicialización de un filtro, y algunos otros datos:

Método Significado
getFilterName() Devuelve el nombre del filtro,
especificado en web.xml
getInitParameter(String name) Devuelve el valor del parámetro, null si
no existe
getInitParameterNames() Devuelve un Enumeration con los
nombres de los parámetros. Null si no
tiene parámetros de iniciacización.
getServletContext() Devuelve una referencia al contexto de
Servlet asociado a la aplicación.

javax.servlet.FilterChain

El contenedor de servlets provee una implementación para esta interface y pasa una instancia de la
misma al método doFilter() del filtro. Posee solo un método:
void doFilter (ServletRequest, ServletResponse): Pasa la petición al próximo componente en la
cadena, otro filtro o el recurso original.

Ejecución de filtros
Como la especificación de Servlets 2.4 permite invocar servlets de las siguientes maneras:
Como un resultado del método RequestDispatcher.forward():
El método forward de la interfaz RequestDispatcher puede ser llamado por el servlet llamante sólo
cuando la salida no ha sido enviada al cliente. Si la información existe en el buffer de respuesta y no

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
ha sido enviada, el contenido deberá limpiarse antes de que el método service del servlet de destino
sea llamado. Si la respuesta ha sido enviada, una excepción del tipo IllegalStateException será
lanzada.
Como un resultado del método RequestDispatcher.include():
El método include de la interfaz RequestDispatcher puede ser llamado en cualquier momento. El
servlet de destino del método include tiene acceso a todos los aspectos de la petición, pero el uso
del objeto response (respuesta) es más limitado: sólo puede escribir información al
ServletOutputStream o al objeto Writer de la respuesta y enviar la respuesta escribiendo el
contenido pegado al final del buffer, o llamando explícitamente al método flushBuffer de la interfaz
ServletResponse. Él no puede establecer las cabeceras o llamar a algún método que afecte a las
cabeceras de la respuesta. Cualquier intento será ignorado.
En páginas de error.

El elemento es obligatorio.
Se debe usar un elemento no se pueden usar ambos dentro de un mismo
elemento
Se pueden usar de 0 a 4 subelementos dentro de un elemento
Por defecto (si no se especifica ningún subelemento los filtros solo se aplican para
peticiones entrantes a la aplicación. Es decir, solo el valor REQUEST es aplicado por defecto.

Configurar un filtro en el archivo web.xml


Dentro de aplicaciones java, un contenedor web utiliza mapeos de filtros para decidir como aplicar
filtros a sus recursos Web.
Un filtro mapeado relaciona un filtro con un componente Web, por nombre o a recursos Web por
patrones de URL. Los filtros son invocados en el orden en el cual aparecen los mapeos en la lista de
mapeos de filtros de un WAR. Se especifica la lista de filtros para un WAR en su descriptor de
despliegue en el fichero de configuración XML como se muestra en la imagen.

Pantalla de modificación de los filtros con el IDE de NetBeans.


Para definir un filtro en el archivo web.xml, se debe utilizar los elementos <filter> y <filter-mapping>.
<!ELEMENT filter (icon?, filter-name, display-name?, description?, filter-class, init-param*) >

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name)) >
<filter>: Cada elemento de este tipo, introduce un nuevo filtro en la aplicación web. Este elemento _
puede contener varios elementos más. Algunos opcionales como: <icon>, <display-name> y <init-
param>.
Otros obligatorios como:
<filter-name>: Define el nombre del filtro dentro del archivo de configuración.
<filter-class>: Define la clase utilizada para instanciar el filtro.
<filter-mapping>: Al igual que <servlet-mapping>, este elemento asocia un filtro con
un conjunto de URLs. Contiene los elementos:
<filter-name>: Identifica el filtro a asociar.
<url-pattern>: Se utiliza para aplicar el filtro a las peticiones que concuerden con el patrón URL.
<servlet-name>: Se utiliza para aplicar el filtro a todas las peticiones que se realicen al servlet asociado.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd">
<filter>
<filter-name>ImpuestosRegistro</filter-name>
<filter-class>filtros.ImpuestosRegistro</filter-class>
<init-param>
<param-name>impuestos</param-name>
<param-value>15</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>ImpuestosRegistro</filter-name>
<url-pattern>/javabeans/subasta.jsp</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>ImpuestosRegistro</filter-name>
<url-pattern>/javabeans/subasta_cambio.jsp</url-pattern>
</filter-mapping>

</web-app>

es el elemento raíz empleado para definir un filtro, dentro de este elemento se anidan :
empleado para definir un nombre descriptivo del filtro y que indica la clase
que contiene el filtro (Dicha clase también sería colocada dentro del directorio classes, o bien ,
dentro de un archivo JAR colocado en el directorio lib, como indica la estructura de WAR's).
Además de estos últimos elementos, también pueden ser agregados los elementos para
indicar elementos de configuración iniciales del filtro; en caso de ser proporcionados dichos valores,
cada uno debe incluir un par de elementos : para especificar el nombre
y valor del parámetro respectivamente.
Una vez definido un filtro, se indica un mapeo para aplicar las reglas de determinado filtro a un URL,
através de los elementos se indica que el filtro llamado ImpuestosRegistro sea
aplicado a las solicitudes de las paginas /javabeans/subasta.jsp y /java/subasta_cambio.jsp.
En el diseño del filtro descrito en la sección anterior se hacia alusión a una cadena de filtros, esta
cadena o grupo quedaría conformada por el número de mapeos que correspodan a determinada
ruta, esto es, si existen dos o tres elementos que cumplan con la ruta, la cadena
quedaría conformada por estos filtros, de igual manera si existiera unicamente un
que coincida con la requisición la cadena equivaldría a un solo filtro.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Los filtros pueden tener los siguientes tipos de distribución:
 REQUEST: Solo cuando la solicitud viene directamente del cliente
 FORWARD: Solo cuando la solicitud ha sido reenviada a un componente (vea Transfiriendo el
control a otro componente Web)
 INCLUDE: Solo cuando la solicitud es procesada por un componente que ha sido incluido (vea
Incluyendo Otros recursos en la respuesta)
 ERROR: Solo cuando la solicitud ha sido procesada mediante el mecanismo de páginas de
error (vea Manejando errores en servlets)
Puede dirigir que los filtros sean aplicados a cualquier combinación de las situaciones anteriores
seleccionando varios tipos de distribución. Si no se especifican tipos la opción por defecto es
REQUEST.

Ver Video: Creacción de un archivo Filter, en la Unidad 9,


en el Módulo 5, en la plataforma elearning

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 10. Integración de Aplicaciones Web
con Bases de Datos
Objetivos
 Integración de aplicaciones web con la api de JDBC
 Realizar desarrollos web que interactuen con Base de datos
 Introducirnos en JNDI

Introducción
JDBC (Java DataBase Connectivity) es un API de Java que permite al programador el acceso a Bases
de Datos usando el lenguaje estándar SQL.
Las tres acciones principales que nos proporcionará JDBC son:
Establecer la conexión con la base de datos.
Enviar sentencias SQL a esa base de datos.
Procesar los resultados obtenidos de la base de datos.
Java soporta dos modelos de acceso a bases de datos:
Modelo Descripción
Modelo de dos capas La aplicación Java o el applet se conectan directamente a la base de
datos.
Por tanto, el driver JDBC específico para conectarse con la base de
datos debe residir en el sistema local (dónde se encuentra la
aplicación o el applet). La base de datos puede estar en cualquier
otra máquina y se accede a ella mediante la red.
Esta es la configuración típica Cliente/Servidor. El programa cliente
envía instrucciones SQL a la base de datos, ésta los procesa y envía
los resultados de vuelta a la aplicación.
Modelo de tres capas Las instrucciones son enviadas a una capa intermedia entre Cliente y
Servidor, que es la que se encarga de enviar las sentencias SQL a la
base de datos y recoger los resultados.
Los driver JDBC no tienen porque residir en la máquina local.
Esta es la configuración típica en Internet, a través de las páginas
ASP, los servlets y demás tecnologías.

Tipos de drivers
Para conectarse a bases de datos individuales, JDBC necesita un driver específico para cada una de
ellas.
Hay cuatro tipos de drivers:
Tipo de Driver Descripción
Puente JDBC-ODBC Este es el driver que se incluye en la plataforma Java2.
Proporciona acceso a base de datos a través de uno o más drivers
ODBC, aprovechando todo lo que ya existe.
El rendimiento se resiente al tener que realizarse la conversión de
las transacciones de JDBC a ODBC.
Java / Binario Este driver realiza la comunicación directa con la libreria que
proporciona el fabricante de la base de datos.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Actualmente, sólo IBM y Oracle proporcionan este tipo de drivers
para acceso a sus base de datos.
WebLogic ofrece dirvers de este tipo para acceder a las base de
datos más populares: SQL Server, Sybase.
100% JAVA/ Protocolo Realizado totalmente en Java, convierte directamente las peticiones
Nativo JDBC del cliente en peticiones de red contra el servidor. Esta
conversión se realiza en el cliente.
100% JAVA/ Protocolo El driver convierte las llamadas JDBC directamente a llamadas
independiente nativas hacia el sistema DBMS de que se trate.
Esta conversión se realiza en el servidor, el cliente puede usar un
driver JDBC genérico.

Diseñar una aplicación web para integrarla con un


DBMS
Gestión de una base de datos Oracle a través de puente jdbc: Oracle.
Instalación del driver.
Los requisitos iniciales son:
Disponer de la base de datos creada.
Adjuntar el fichero jar que nos suministre el proveedor para poder conectarnos a su base de datos.
En la siguiente imagen adjuntamos el fichero jar a nuestr proyecto con las clases necesarias para
trabajar con una base de datos Oracle.

El paso 1 será cargar el driver que suminstra Oracle para poder conectarnos a su motor de base de
datos.
// Cargamos driver ORACLE
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());

Conexión
Una vez cargado el driver, podemos realizar la conexión.
Esta conexión se realiza mediante el método getConnection() de la clase DriverManager.
Connection conn = DriverManager.getConnection
("jdbc:oracle:thin:@Servidor:1521:NombreBD","usuario", "password");

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Métodos de la clase
connection
void clearWarnings()
Borra todos los warnings comunicados por este objeto
Connection
void close()
Cierra la conexión liberando todos los recursos que estuviese
utilizando.
Statement createStatement()
Crea una sentencia (representada por el objeto Statement)
que permitirá enviar comandos SQL a la base de datos.
SQLWarning getWarnings()
Devuelve el primer warning provocado por llamadas sobre
este objeto Connection.
boolean isClosed()
Comprueba si la conexión está cerrada.
boolean isReadOnly()
Comprueba si la conexión está en modo de sólo lectura.
void setReadOnly(boolean readOnly)
Pone esta conexión en modo sólo lectura.

Creando sentencias SQL


A través del objeto Connection, podemos crear sentencias. Para ello se usará el método
createStatement() el cual devolverá un objeto de tipo Statement.
Statement sentencia=conexion.createStatement();
Sobre el objeto Statement podemos usar los siguientes métodos:

Métodos de la clase
Statement
void cancel()
Cancela este objeto Statement si el DBMS y el driver
soportan el abortar sentencias SQL.
void clearWarnings()
Borra todos los warnings comunicados por este objeto
Statement.
void close()
Cierra este objeto Statement y libera todos los recursos que
estaba usando.
boolean execute(String sql)
Ejecuta una sentencia SQL que puede retornar múltiples
resultados.
ResultSet executeQuery(String sql)
Ejecuta una sentencia SQL que devuelve un único ResultSet.
Por ejemplo, un SELECT.
int executeUpdate(String sql)
Ejecuta una sentencia SQL de tipo SQL INSERT, UPDATE o
DELETE.
Connection getConnection()
JDBC 2.0 Devuelve el objeto Connection que produjo este
objeto Statement.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
int getMaxFieldSize()
Devuelve el número máximo de bytes permitidos en el valor
de cualquier columna.
int getMaxRows()
Devuelve el número máximo de registros que puede
contener un ResultSet.
boolean getMoreResults()
Se mueve al siguiente registro del objeto Statement.
int getQueryTimeout()
Devuelve el número de milisegundos que esperará el driver a
que una sentencia SQL se ejecute.
ResultSet getResultSet()
Devuelve el resultado actual como un objeto ResultSet.
SQLWarning getWarnings()
Devuelve el primer warning comunicado en la llamadas sobre
este objeto Statement.
void setCursorName(String name)
Define el nombre del cursor que será usado por los métodos
execute de los objetos Statement siguientes.
void setMaxFieldSize(int max)
Pone el número máximo de bytes para una columna.
void setMaxRows(int max)
Pone el número máximo de registros que un ResultSet puede
contener.
void setQueryTimeout(int seconds)
Pone el número de segundos que esperará el driver a que
una sentencia se ejecute.

Recuperando registros
Para recuperar información de la base de datos se recurre al método executeQuery(), el cual
devuelve un objeto de tipo ResultSet
ResultSet resultado=sentencia.executeQuery("SELECT * FROM tabla");
while(resultado.next()){
String titulo=resultado.getString("TITULO");
String autor=resultado.getString("AUTOR");
int precio=resultado.getInt("Precio");
Date publicacion=resultado.getDate("PUBLICACION");
System.out.println(....imprimir campos...");
}
Como se puede ver en los métodos de abajo, cada getxxx tiene dos posibilidades: dar el nombre de
la columna como un String o dar un índice que hace referencia al campo en concreto (el índice
comienza en 1 y se refiere al ResultSet que obtenemos de la consulta y no a la base de datos
completa).
Los métodos que podemos usar sobre el objeto ResultSet son:
Métodos de ResultSet
boolean absolute(int row)
JDBC 2.0 Permite situarnos en un registro en concreto.
void afterLast()
JDBC 2.0 Permite situarnos después del último registro.
void beforeFirst()
JDBC 2.0 Permite situarnos antes del primer registro.
void close()

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Cierra el objeto ResultSet y se liberan los recursos que
estaba usando.
void deleteRow()
JDBC 2.0 Borra el registro del ResultSet en el que nos
encontramos actualmente.Deletes the current row from the result
set and the underlying database.
boolean first()
JDBC 2.0 Nos colocamos en el primer registro.
BigDecimal getBigDecimal(int columnIndex)
JDBC 2.0 Obtiene el valor de una columna del registro
actual como un java.math.BigDecimal con precisión completa.
BigDecimal getBigDecimal(String columnName)
JDBC 2.0 Obtiene el valor de una columna del registro
actual como un java.math.BigDecimal con precisión completa.
InputStream getBinaryStream(int columnIndex)
Obtiene el valor de una columna como un stream de bytes.
InputStream getBinaryStream(String columnName)
Obtiene el valor de una columna como un stream de bytes.
boolean getBoolean(int columnIndex)
Obtiene el valor de una columna como un boolean.
boolean getBoolean(String columnName)
Obtiene el valor de una columna como un boolean.
byte getByte(int columnIndex)
Obtiene el valor de una columna como un byte.
byte getByte(String columnName)
Obtiene el valor de una columna como un byte.
byte[] getBytes(int columnIndex)
Obtiene el valor de una columna como un array de bytes.
byte[] getBytes(String columnName)
Obtiene el valor de una columna como un array de bytes.
Reader getCharacterStream(int columnIndex)
JDBC 2.0 Obtiene el valor de una columna como un
Reader.
Reader getCharacterStream(String columnName)
JDBC 2.0 Obtiene el valor de una columna como un
Reader.
String getCursorName()
Obtiene el nombre del cursor SQL usado por este
ResultSet.
Date getDate(int columnIndex)
Obtiene el valor de una columna como un objeto
java.sql.Date.
Date getDate(int columnIndex, Calendar cal)
JDBC 2.0 Obtiene el valor de una columna como un objeto
java.sql.Date.
Date getDate(String columnName)
Obtiene el valor de una columna como un objeto
java.sql.Date.
Date getDate(String columnName, Calendar cal)
Obtiene el valor de una columna como un objeto
java.sql.Date.
double getDouble(int columnIndex)
Obtiene el valor de una columna como un double.
double getDouble(String columnName)
Obtiene el valor de una columna como un double.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
float getFloat(int columnIndex)
Obtiene el valor de una columna como un float.
float getFloat(String columnName)
Obtiene el valor de una columna como un float.
int getInt(int columnIndex)
Obtiene el valor de una columna como un int.
int getInt(String columnName)
Obtiene el valor de una columna como un int.
long getLong(int columnIndex)
Obtiene el valor de una columna como un long.
long getLong(String columnName)
Obtiene el valor de una columna como un long.
Object getObject(int columnIndex)
Obtiene el valor de una columna como un object.
Object getObject(String columnName)
Obtiene el valor de una columna como un object.
short getShort(int columnIndex)
Obtiene el valor de una columna como un short.
short getShort(String columnName)
Obtiene el valor de una columna como un short.
Statement getStatement()
JDBC 2.0 Devuelve el objeto Statement que produjo este
objeto ResultSet.
String getString(int columnIndex)
Obtiene el valor de una columna como un String.
String getString(String columnName)
Obtiene el valor de una columna como un String.
Time getTime(int columnIndex)
Obtiene el valor de una columna como un objeto
java.sql.Time.
Time getTime(int columnIndex, Calendar cal)
Obtiene el valor de una columna como un java.sql.Time.
Time getTime(String columnName)
Obtiene el valor de una columna como un java.sql.Time.
Time getTime(String columnName, Calendar cal)
Obtiene el valor de una columna como un java.sql.Time.
int getType()
JDBC 2.0 Devuelve el tipo de este ResultSet.
SQLWarning getWarnings()
Retorna el primer warning comunicado en llamadas a este
ResultSet.
void insertRow()
JDBC 2.0 Inserta los contenidos del registro en el objeto
ResultSet y en la base de datos.
boolean isAfterLast()
JDBC 2.0 Detecta si el cursor está después del último
registro.
boolean isBeforeFirst()
JDBC 2.0 Detecta si el cursor está antes del primer
registro.
boolean isFirst()
JDBC 2.0 Detecta si el cursor está en el primer registro.
boolean isLast()
JDBC 2.0 Detecta si el cursor está en el último registro.
boolean last()

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
JDBC 2.0 No sitúa en el último registro.
boolean next()
Mueve el cursor al siguiente registro.
boolean previous()
JDBC 2.0 Mueve el cursor al registro anterior.
void refreshRow()
JDBC 2.0 Refresca la fila actual con su valor más reciente
en la base de datos.
boolean relative(int rows)
JDBC 2.0 Nos movemos el número de registros indicando
desde la posición actual.
boolean rowDeleted()
JDBC 2.0 Indica si un registro ha sido borrado. Contrasta
nuestro ResultSet con la base de datos.
boolean rowInserted()
JDBC 2.0 Indica si el registro actual ha sufrido alguna
inserción.
boolean rowUpdated()
JDBC 2.0 Indica si el registro actual ha sido actualizado.
void updateBigDecimal(int columnIndex, BigDecimal x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor BigDecimal indicado.
void updateBigDecimal(String columnName, BigDecimal x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor BigDecimal indicado.
void updateBoolean(int columnIndex, boolean x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor boolean indicado.
void updateBoolean(String columnName, boolean x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor boolean indicado.
void updateByte(int columnIndex, byte x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor byte indicado.
void updateByte(String columnName, byte x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor byte indicado.
void updateBytes(int columnIndex, byte[] x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el array de bytes indicado.
void updateBytes(String columnName, byte[] x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el array de bytes indicado.
void updateDate(int columnIndex, Date x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Date indicado.
void updateDate(String columnName, Date x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Date indicado.
void updateDouble(int columnIndex, double x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor double indicado.
void updateDouble(String columnName, double x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor double indicado.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
void updateFloat(int columnIndex, float x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor float indicado.
void updateFloat(String columnName, float x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor float indicado.
void updateInt(int columnIndex, int x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor int indicado.
void updateInt(String columnName, int x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor int indicado.
void updateLong(int columnIndex, long x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor long indicado.
void updateLong(String columnName, long x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor long indicado.
void updateNull(int columnIndex)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor null indicado.
void updateNull(String columnName)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor null indicado.
void updateObject(int columnIndex, Object x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Object indicado.
void updateObject(String columnName, Object x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Object indicado.
void updateRow()
JDBC 2.0 Actualiza la base de datos con los nuevos
contenidos del registro actual.
void updateShort(int columnIndex, short x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor short indicado.
void updateShort(String columnName, short x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor short indicado.
void updateString(int columnIndex, String x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor String indicado.
void updateString(String columnName, String x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor String indicado.
void updateTime(int columnIndex, Time x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Time indicado.
void updateTime(String columnName, Time x)
JDBC 2.0 Actualiza la columna indicada del registro actual
con el valor Time indicado.
boolean wasNull()
Comunica si la última columna leída tiene un valor SQL
nulo.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Para obtener información relativa a cada campo basta con utilizar el método getMetaData() sobre el
objeto ResultSet y obtenemos un objeto ResultSetMetaData sobre el que se pueden usar los
siguientes métodos:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Métodos de
ResultSetMetaData
int getColumnCount()
Devuelve el número de columnas de este ResultSet.
int getColumnDisplaySize(int column)
Indica el ancho máximo de la columna especificada en
caracteres.
String getColumnName(int column)
Devuelve el nombre de la columna especificada.
int getColumnType(int column)
Devuelve el tipo SQL de la columna especificada.
String getColumnTypeName(int column)
Devuelve el tipo de dato de la columna según la base de
datos.
int getPrecision(int column)
Obtiene la precisión usada en la columna. Tiene sentido en
datos decimales.
int getScale(int column)
Obtiene el número de dígitos usados a la derecha del
punto decimal.
String getTableName(int column)
Gets a column's table name.
boolean isAutoIncrement(int column)
Indica si la columna especificada es automáticamente
numerada, esto es de sólo lectura.
boolean isCaseSensitive(int column)
Indica si la columna indicada es sensible a mayúsculas y
minúsculas.
boolean isCurrency(int column)
Indica se la columna indicada es un valor de moneda.
int isNullable(int column)
Indica si la columna indicada permite valores null.
boolean isReadOnly(int column)
Indica si la columna indicada es de sólo lectura.
boolean isSearchable(int column)
Indica si la columna puede ser usada en un claúsula
where.
boolean isSigned(int column)
Indica si los valores de la columna especificada son
número con signo.
boolean isWritable(int column)
Indica si se puede escribir en la columna especificada.

Ejemplo de aplicación web que recupere información de una base de datos


Crear un sitio web para poder visualizar información de las distribuidoras de un cine.
Tabla DISTRIBUIDORAS en Oracle
CREATE TABLE DISTRIBUIDORAS(DISTRIBUIDORA varchar2(40),IMAGEN varchar2(20),INTERNET varchar2(35));
INSERT INTO DISTRIBUIDORAS VALUES('20 th Centyry Fox','20century.jpg','http://www.fox.es/');
INSERT INTO DISTRIBUIDORAS VALUES('Aurum','aurum.gif','http://www.aurum.es/');
INSERT INTO DISTRIBUIDORAS VALUES('Columbia Tristar','columbia.jpg','http://www.columbia-tristar.es/');
INSERT INTO DISTRIBUIDORAS VALUES('Filmax','filmax.gif','http://www.filmax.com/');
INSERT INTO DISTRIBUIDORAS VALUES('Lauren Films','laurenfilmx.gif','http://www.laurenfilm.es/');
INSERT INTO DISTRIBUIDORAS VALUES('Lola Films','lolafilms.gif','http://www.lolafilms.com/');

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
INSERT INTO DISTRIBUIDORAS VALUES('MGM','mgm.jpg','http://www.mgm.com/');
INSERT INTO DISTRIBUIDORAS VALUES('Miramax','miramax.jpg','http://www.miramax.com/');
INSERT INTO DISTRIBUIDORAS VALUES('New Line Cinema','newlinecinema.jpg','http://www.newline.com/');
INSERT INTO DISTRIBUIDORAS VALUES('Tri-Pictures','tripictures.gif','http://www.tripictures.com/');
INSERT INTO DISTRIBUIDORAS VALUES('UIP - Paramount,Universal y
Dreamworks','paramount.jpg','http://www.uip.es/');
INSERT INTO DISTRIBUIDORAS VALUES('Walt Disney','waltdisney.jpg','http://www.disney.com/');
INSERT INTO DISTRIBUIDORAS VALUES('Warner Bross','warner.gif','http://www.warnerbros.com/');
commit;

La página Distribuidoras.jsp debe cargar los datos de los tres campos de la tabla distribuidoras:
 Mostrar en una etiqueta img la imagen de la distribuidora.
 Cargar en un hipervínculo el nombre de la distribuidora.
 Al pulsar sobre la distribuidora debemos redirigir al usuario al sitio web de la distribuidora.

Código JSP
<%@page language = "java" import="java.sql.*" %>

<% ResultSet rs; //Para los resultados de la consulta%>


<html>
<head>
<title>PRINCIPALES DISTRIBUIDORAS</title>
<link Rel="stylesheet" HRef="ESTILOS\estilo.css" Type="text/css">
</head>
<body>
<center>
<b class=titulo>PRINCIPALES DISTRIBUIDORAS</b>
</center>
<BR>
<table border="0" align=center cellspacing="10" cellpadding="4" width=400 class=gris>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%-- Aqui la lista creada en un bucle--%>
<%
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());

Connection conexion = DriverManager.getConnection


("jdbc:oracle:thin:@Servidor:1521:BdDistribuidora","system", "a1b2");

Statement sentencia=conexion.createStatement();
rs=sentencia.executeQuery("SELECT internet,distribuidora,imagen from
distribuidoras");

int par=1; //Para controlar que muestre dos por fila

while(rs.next()){

String direccion=rs.getString(1);
String nombre=rs.getString(2);
String imagen=rs.getString(3);

if(par%2!=0){
out.println("<tr>");
}
String enlazar= "<a href="+direccion +" TARGET=_blank
class=mediano>";
out.println("<TD><table border=0 cellpadding=4 width=180;><tr>");
out.println("<tD width=30>"+enlazar+"<img
src=IMAGENES\\DISTRIBUIDORAS\\"+imagen+" alt=_
\""+nombre+"\" border=0 width=60 height=42></a></td>");
out.println("<td
align=left>"+enlazar+nombre+"</a></td></tr></table></TD>");

if(par%2==0){
out.println("</tr>");
}
par++;
}

if(par%2==0){
out.println("</tr>");
}

%>
</table>

</body>

</html>

API de Java Naming and Directory Interface (JNDI)


La Interfaz de Nombrado y Directorio Java (Java Naming and Directory Interface) es una Interfaz de
Programación de Aplicaciones (API) para servicios de directorio. Esto permite a los clientes descubrir
y buscar objetos y nombres a través de un nombre y, como todas las APIs de Java que hacen de
interfaz con sistemas host, es independiente de la implementación subyacente. Adicionalmente,
especifica una interfaz de proveedor de servicio (SPI) que permite que las implementaciones del

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
servicio de directorio sean integradas en el framework. Las implementaciones pueden hacer uso de
un servidor, un fichero, o una base de datos; la elección depende del vendedor.

Los servicios de Nombre y Directorio


Análogos a un operador telefónico
Si quieres llamar a alguien pero desconoces su número de teléfono, entonces puedes llamar a un
teléfono de información de tu compañía telefónica para buscar (look up) el número de teléfono de la
persona que quieres llamar. Le das al operador el nombre de la persona a localizar y el operador
busca el número de teléfono y te conecta a dicha persona.
Entidad que realiza las siguientes tareas:
asocia nombres con objetos:
a esto se le llama unión (binding) de nombres a Objetos
facilita la búsqueda de Objetos basados en nombres
Soportados por diferentes productos
NIS (Network Information service) en redes Solaris y Unix
NDS (Novell Directory Services) en redes Novell
ADSI (Active Directory Service Interface) en redes Microsoft
LDAP (Lightweight Directory Access Protocol) fue creado a principios de los años noventa como
protocolo de directorio estándar.
hoy en día LDAP es el protocolo con más aceptación.
los distribuidores NIS, NDS Y ADSI proporcionan interfaces de sus protocolos propietarios para que
LDAP se pueda comunicar con ellos.

Interacción con los servicios de Nombre y Directorio


Antes de que existiera JNDI, los desarrolladores Java tenían que programar específicamente un
servicio de directorios en una red concreta. Este hecho complicaba bastante las cosas por que cada
servicio de directorio de red tiene sus propias APIs propietarias.
Esta imagen nos muestra como se interactuaba con estos diferentes servicios de directorio sin JNDI

JNDI proporciona una API común a una variedad de servicios de directorios. Este API está incluida
como parte estándar de Java, del mismo modo que JDBC proporciona una API estándar para las
Bases de Datos Relacionales.
Esta imagen nos muestra cómo JNDI unifica el acceso a servicios de directorio de redes
heterogéneos:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Proveedores de servicios JNDI
En grandes Centros de Cálculo se suele disponer de un Ordenador que realiza las labores de
proveedor de servicios JNDI.
De esta forma todo el mundo que quiera acceder a una BDS particular solamente tiene que
comunicarse con el proveedor de servicios JNDI e indicarle el nombre de directorio de la BDS en
cuestión.
La ventaja de utilizar esta forma de acceder a una BDS es que ésta puede cambiar su localización,
es decir su direección IP, e incluso también puede cambiar el nombre de la BDS pero todos estos
cambios son tranparentes al usuario que quiere conectar con dicha BDS.
Un proveedor de servicios JNDI es en definitiva un conjunto de Clases Java. Una de estas Clases
tiene que implementar la Interfaz DirectoryContext que a su vez hereda de la Interfaz Context.
El proveedor de servicios JNDI necesita que el usuario que requiere un servicio se autentifique a
través de un nombre de usuario y una contraseña.

Ver Video: Integración con Base de Datos, en la Unidad 10,


en el Módulo 5, en la plataforma elearning

Laboratorio: Paginación de registros.


Objetivo
Realizar una aplicación que recupere registros de la tabla emp de Oracle y los muestre paginados.
Enunciado
 Crear una página jsp que permita paginar los registros de los empleados de cinco en cinco,
diez en diez, quince en quince o de veinte en veinte
 Mostrar valores numéricos para poder paginar los registros dependiendo del número de
registros que queden.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Creación de la table emp e inserción de registros:
CREATE TABLE EMP
(EMP_NO NUMBER(4,0)
CONSTRAINT EMP_PRIMARY_KEY PRIMARY KEY,
APELLIDO VARCHAR2(10)
NOT NULL,
OFICIO VARCHAR2(10)
CONSTRAINT EMP_CHK_OFICIO CHECK(OFICIO
IN('ANALISTA','DIRECTOR','EMPLEADO','PRESIDENTE','VENDEDOR')),
DIR NUMBER(4,0)
CONSTRAINT EMP_SELF_KEY REFERENCES EMP(EMP_NO),
FECHA_ALT DATE
DEFAULT SYSDATE,
SALARIO NUMBER(10,0)
CONSTRAINT EMP_CHK_SALARIO CHECK(SALARIO BETWEEN 100000 AND 999999),
COMISION NUMBER(10,0),
DEPT_NO NUMBER(2,0)
NOT NULL,
CONSTRAINT EMP_FOREIGN_KEY FOREIGN KEY(DEPT_NO) REFERENCES
DEPT(DEPT_NO)
);

insert into emp values('7839','rey','PRESIDENTE',null,'17-nov-95',650000,null,10);


insert into emp values('7698','negro','DIRECTOR',7839,'01-may-95',370500,null,30);
insert into emp values('7566','jimenez','DIRECTOR',7839,'02-abr-95',386750,null,20);
insert into emp values('7782','cerezo','DIRECTOR',7839,'09-jun-95',318500,null,10);
insert into emp values('7499','arroyo','VENDEDOR',7698,'20-feb-94',208000,39000,30);
insert into emp values('7521','sala','VENDEDOR',7698,'22-feb-95',162500,65000,30);
insert into emp values('7654','martin','VENDEDOR',7698,'29-jul-95',162500,182000,30);
insert into emp values('7844','tovar','VENDEDOR',7698,'08-jul-95',195000,0,30);
insert into emp values('7900','jimeno','EMPLEADO',7698,'03-dic-95',123500,null,30);
insert into emp values('7902','fernandez','ANALISTA',7566,'03-dic-95',390000,null,20);
insert into emp values('7788','gil','ANALISTA',7566,'09-nov-95',390000,null,20);
insert into emp values('7369','sanchez','EMPLEADO',7902,'17-dic-94',104000,null,20);
insert into emp values('7876','alonso','EMPLEADO',7788,'23-jul-95',143000,null,20);
insert into emp values('7934','muñoz','EMPLEADO',7782,'23-ene-96',169000,null,10);

Insertar el siguiente código en la página JSP.


<%@ page contentType="text/html"%>
<%@page import="java.io.*, java.sql.*"%>

<%! int vReg; %>


<%! int vPosicion; %>

<%
if (request.getParameter("registros") != null)
vReg = Integer.parseInt(request.getParameter("registros"));
else
vReg = 5;

if (request.getParameter("posicion") != null)
vPosicion = Integer.parseInt(request.getParameter("posicion"));
else
vPosicion = 1;
%>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<script language="javascript">
function paginar(pNumReg)
{
var vDestino = "paginacion.jsp?registros=" + pNumReg + "&posicion=1";
window.location = vDestino;
}
</script>

<style>
BODY {
text-align: center;
background-color: #EEEEEE;
}
TD, SELECT, OPTION {
background-color: #CCDDFF;
font-size: 12px;
color: #660099;
border: 1px solid #9999CC;
font-family: tahoma;
}
TH {
font-size: 14px;
font-family: arial;
text-align: center;
}
A, A.link, A.visited {
text-decoration: none;
font-size: 12px;
color: #6699CC;
}
A:hover {
color: #660099;
}
.CENTRO {
background-color: #660099;
font-weight: bold;
color: #FFFFFF;
}
</style>
</HEAD>

<BODY>
<table style="border: 1px solid #99CCFF; background-color: #DDDDDD; width: 500px;">
<tr>
<td colspan="3" style="text-align: right; color: #000000; background-color: #FFCC99;">
registros por pantalla _
<select name="fNumRegistros" style="width: 50px;" onchange="paginar(this.value);">
<%

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
_
for (int i=5; i<=20; i+=5)

_
{

_
if (i == vReg)

_
{

_
%>

_
<option value="<%= i %>" selected> <%= i %> </option>

_
<%

_
}

_
else

_
{

_
%>

_
<option value="<%= i %>"> <%= i %> </option>

_
<%

_
}

_
}
%>

_
</select>
</td>
</tr>
<tr><td colspan="3" style="background-color: #DDDDDD; border: 0px;"> &nbsp; </td></tr>
<tr>
<th colspan="3"> Listado de empleados </th>
</tr>
<tr>
<td class="CENTRO" style="width: 50px;"> Num. </td>
<td class="CENTRO" style="width: 225px;"> Apellido </td>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<td class="CENTRO" style="width: 225px;"> Puesto </td>
</tr>
<%
Connection vConexion;
Statement vSentencia;
ResultSet vRegistros;
String vConsulta;
int vNumReg = 0;

try
{
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
}
catch(Exception e){ System.out.println("Error en la carga del driver..."); }

try
{

vConexion = DriverManager.getConnection ("jdbc:oracle:thin:@Servidor:1521:BdEmpleados",_


"system", "a1b2");

vSentencia =
vConexion.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, _
ResultSet.CONCUR_UPDATABLE);
vConsulta = "SELECT emp_no, apellido, oficio FROM emp ORDER BY
apellido;";
vRegistros = vSentencia.executeQuery(vConsulta);

vRegistros.last();
vNumReg = vRegistros.getRow();
vRegistros.absolute(vPosicion);

for (int i=0; i<vReg && !vRegistros.isAfterLast(); i++)


{
%>
<tr>
<td> <%=vRegistros.getString(1)%> </td>
<td> <%=vRegistros.getString(2)%> </td>
<td> <%=vRegistros.getString(3)%> </td>
</tr>
<%
vRegistros.next();
}

%>
<tr>
<th colspan="3" style="text-align: right;">
<%
for (int p=0, j=1; p <= vNumReg-1; p += vReg, j++)
{
%>
<a
href="paginacion.jsp?registros=<%=vReg%>&posicion=<%=p+1%>">_
<%=j%></a> &nbsp;
<%
}

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
%>
</th>
</tr>
<%
vConexion.close();
}
catch(SQLException e) { System.out.println(e.toString()); }
catch(Exception e) { System.out.println(e.toString()); }
%>

</table>
</BODY>
</HTML>

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 11. Desarrollo de páginas JSP
Objetivos
 Entender la tecnología JSP y sus tipos de construcciones.
 Desarrollar aplicaciones con los elementos de script de JSP.
 Utilizar las acciones JSP que usan construcciones en sintaxis XML para controlar el
comportamiento de la máquina servlet

Introducción a la tecnología de páginas JSP


Cuando una JSP es invocada por primera vez, ésta es convertida a un servlet normal, en el cual la
parte HTML estática se imprime directamente sobre el flujo de salida asociado con el método service
de dicho servlet.
Los desarrolladores de las JSP pueden invocarlas por primera vez al instalarlas si quieren evitar el
retardo en el que se incurre en la primera invocación, cuando la JSP es convertida a un servlet y el
servlet es compilado y cargado.
Hay tres tipos de construcciones JSP que podemos incluir en una página:

Profundicemos un poco más en cada una de estas construcciones:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Elementos de Script JSP
Los elementos de script de JSP te permite insertar código Java en el servlet que será generado a
partir de la página JSP. Hay tres formas:
Las expresiones de la forma
<%= expression %>
serán evaluadas e insertadas en la salida.
Los Scriptlets de la forma
<% code %>
serán insertadas en el método service del servlet.

Las declaraciones de la forma


<%! code %>
serán insertadas en el cuerpo del servlet, fuera de cualquier método.
Expresiones JSP
Una expresión JSP es usada para insertar valores Java directamente en la salida. Tiene el siguiente
formato:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%= Java Expression %>
La expresión es evaluada, convertida a String e insertada en la página. La evaluación es realizada en
tiempo de ejecución (cuando la página es solicitada), y por eso tiene acceso completo a la
información de la petición.
Existen un número de variables predefinidas que se pueden usar (no podrán ser definidas como
variables nuestras dentro de la página JSP):

JSP Scriptlets
Si queremos hacer algo más complejo que insertar una simple expresión, Los scriptlets JSP te
permiten insertar cualquier tipo de código java dentro del método servlet que será construido para
generar la página. Tienen el siguiente formato:
<% Java Code %>
Los Scriptlets tienen también acceso a las variables definidas automáticamente por el sistema.
<%
String consultadatos = request.getQueryString();
out.println("Datos obtenidos: " + consultadatos);
%>
El siguiente fragmento JSP que contiene mezcla de texto HTMl y scriptlets:
<% if (Math.random() < 1.1) { %>
Hola
<% } else { %>
Adios
<% } %>
Si queremos usar "%>" dentro del scriptlet, debes usar "%\>" .
Por último, recordar que el equivalente XML de <% Code %> es:
<jsp:scriptlet>
Code
</jsp:scriptlet>
Declaraciones JSP
Una declaración JSP te permite definir métodos o campos que serán insertados en el cuerpo
principal de la clase servlet (fuera del método service que procesa la petición). Tiene el siguiente
formato:
<%! Java Code %>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ya que las declaraciones no generan ninguna salida por sí solas, ellos normalmente se usan en
conjunción con expresiones o scriptlets JSP.
Directivas JSP
Una directiva JSP afecta a la estructura completa de la clase del servlet que se crea a partir de la
página JSP. Normalmente tiene el siguiente formato:
<%@ directive attribute="value" %>
Sin embargo, puedes también combinar multiples atributos en una única directiva, de la siguiente
manera:
<%@ directive attribute1="value1"
attribute2="value2"
...
attributeN="valueN" %>
Hay dos tipos principales de directivas:

Directiva JSP page


La directiva page te permite definir uno o más de los siguientes atributos (sensibles a mayúsculas y
minúsculas):

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Directiva JSP include
Esta directiva te permite incluir ficheros en el momento en el que la página JSP está siendo
convertida en servlet. El formato es el siguiente:
<%@ include file="relative url" %>
La URL especificada es considerada normalmente de forma relativa a la página JSP desde la que se
hace la referencia, pero se puede indicar al servidor que la interprete de forma relativa desde el
directorio raiz de dicho servidor comenzando la URL con "/" (forward slash).
Los contenidos del fichero incluido son interpretados como texto JSP normal y, por tanto, puede
incluirse:
- HTML estático.
- Elementos de script, directivas y acciones.
<%@page contentType="text/html"%>
<html>
<head><title>JSP Page</title></head>
<body>
<%@ include file="ejemplo.html" %>
</ body>
</ html>

Acciones
Las acciones JSP usan construcciones en sintaxis XML para controlar el comportamiento de la
máquina servlet.

jsp:include
Esta acción te permite insertar ficheros en la página que está siendo generada. La sintaxis es:
<jsp:include page="relative URL" flush="true" />

A diferencia de la directiva include, la cual inserta el fichero en el momento en el que la página JSP
es convertida a un servlet, esta acción inserta el fichero en el momento en el que la página es

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
solicitada. Esto pierde un poco de eficiencia y no permite que la página contenga código JSP general
(no se pueden manipular las cabecereas HTTP, por ejemplo), pero gana significativamente en
flexibilidad.
<%@page contentType="text/html"%>
<html>
<head><title>JSP Page</title></head>
<body>
<OL>
<LI><jsp:include page="Item1.html" flush="true"/>
<LI><jsp:include page="Item2.html" flush="true"/>
</OL>
</BODY>
</HTML>
jsp:useBean
Esta acción te permite cargar un JavaBean para ser usado en una página JSP. Esta es una capacidad
muy útil porque permite explotar la reusabilidad de las clases de Java sin sacrificar las ventajas de
JSP añade sobre los servlets. La sintaxis más simple para especificar el bean que será usado es:
<jsp:useBean id="name" class="package.class" />
Esto significa:
" instancia un objeto de la clase especificada en el atributo class, y enlazalo a una variable con el
nombre especificado en el atributo id".
Una vez que tenemos una instancia de un bean, podemos modificar sus propiedades mediante la
acción jsp:setProperty, o usando un scriptlet que llame a un método del objeto referenciado por el
nombre de la variable especificado en el atributo id.
Podemos leer alguna de sus propiedades mediante la acción jsp:getProperty o usando algún método
que nos devuelva el valor de la propiedad.
En el siguiente ejemplo creamos un JavaBeans con un método llamado hora que devuelve la hora
formateada:
Bean (Bean1.class)

package BeansPropios;

import java.util.*;
import java.text.*;

public class Bean1{

private Calendar hora;


private Date horaactual;
private DateFormat formato;
private String cadhora;

public String Hora(){


horaactual= hora.getInstance().getTime();
formato= DateFormat.getTimeInstance();
cadhora=formato.format(horaactual);
return cadhora;
}
}
La página JSP, mediante la acción Jsp:useBean hará uso del método hora.
Página JSP.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%@page contentType="text/html"%>

<html>
<head>
<title>HORA DEL SISTEMA CON JAVABEAN</TITLE>
</HEAD>

<BODY BGCOLOR='#AAB42A' text='navy'>


<jsp:useBean id="objeto" scope="session" class="BeansPropios.Bean1"/>
<center>
<h1>HORA DEL SISTEMA <%=objeto.Hora()%></H1>
</center>
</body>
</html>

jsp:setProperty.
Haremos uso de la acción jsp:setProperty para dar valores a las propiedades de los beans que han
sido referenciados anteriormente. Se puede hacer en dos contextos. En el primero, puedes usar
jsp:setProperty fuera de jsp:useBean:
<jsp:useBean id="nombreBean" ... />
...
<jsp:setProperty name="nombreBean" property="nombre ... />

En el segundo contexto, el jsp:setProperty puede aparecer dentro del cuerpo de un jsp:useBean:


<jsp:useBean id="nombreBean" ... >
...
<jsp:setProperty name="nombreBean" property="nombre" ... />
</jsp:useBean>
En este caso, el jsp:setProperty es ejecutado sólo si un nuevo objeto es instanciado (no si el Bean
ya se encontró), mientras que en el primer caso se ejecuta independientemente de lo que ocurra
con el Bean.
Hay cuatro posible atributos de jsp:setProperty:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
En el siguiente ejemplo desarrollar una aplicación web que nos permita generar números aleatorios
entre un valor inicial y uno final.
Incorporar el algoritmo en un Java Beans donde almacenemos el valor inicial, el final y la cantidad
de números en tres propiedades del Java Beans.
Bean
package BeansPropios;

public class BJSPPARAMETROS {

public BJSPPARAMETROS() {
}

private int cantidad, inferior, superior;


public void setCantidad (int a) {cantidad = a;}
public void setInferior (int a) {inferior = a;}
public void setSuperior (int a) {superior = a;}

public int [] Devolver()


{
int [] aleatorios = new int [cantidad];
boolean existe = false;

for (int i=0; i<aleatorios.length; i++)


{
do {
existe = false;
Double d = new Double (Math.random()*(superior-inferior+1));
int candidato = inferior + d.intValue();
for (int j=0; j<aleatorios.length; j++)
{
if (aleatorios[j] == candidato)
{
existe = true;
break;
}

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
}
if (!existe)
{
aleatorios[i] = candidato;
}
} while (existe);
}
return aleatorios;
}
}
Página html
<html>
<head>
<title>NUMEROS ALEATORIOS</TITLE>
</head>
<BODY bgcolor=#aab42a text=navy>
<form action="pagina.jsp" method=post>
<center>
GENERAR<INPUT TYPE=TEXT NAME=cantidad SIZE=5> NUMEROS ALEATORIOS ENTRE
<INPUT TYPE=TEXT NAME=inferior size=5> Y <INPUT TYPE=TEXT NAME=superior size=5>
<br><br>
<input type=submit value="GENERAR">
</center>
</FORM>

</BODY>
</html>
En la página jsp asignaremos los valores de las cajas de texto a las propiedades cantidad,inferior y
superior.
pagina.jsp
<%@page contentType = "text/html" %>
<html>
<head><title>Numero aleatorio sin repetición</title></head>
<body bgcolor = #AAB42A text = navy>
<jsp:useBean id="objeto" scope="session" class="BeansPropios.BJSPPARAMETROS" />
<jsp:setProperty name="objeto" property="cantidad" param = "cantidad"/>
<jsp:setProperty name="objeto" property="inferior" param = "inferior"/>
<jsp:setProperty name="objeto" property="superior" param = "superior"/>
<font size ="6">Números generados</FONT>
<BLOCKQUOTE>
<ol type = "disc">
<%
int [] resultado = objeto.Devolver();
for (int i=0; i<resultado.length; i++)
{%>
<li><%=resultado[i]%></li>
<%}%>

</ol>
<% } else { %>
<h3> no hay suficientes numeros en el intervalo solicitado </h3>
<% } %>
</body>
</html>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Como las cajas de texto y las propiedades cantidad, inferior y superior tienen el mismo nombre
podemos asignar el valor automáticamente colocando un “*”.
<%@page contentType = "text/html" %>
<html>
<head><title>Numero aleatorio sin repetición</title></head>
<body bgcolor = #AAB42A text = navy>
<jsp:useBean id="objeto" scope="session" class="BeansPropios.BJSPPARAMETROS" />
<jsp:setProperty name="objeto" property="*" />
<font size ="6">Números generados</FONT>
<BLOCKQUOTE>
<ol type = "disc">
<%
int [] resultado = objeto.Devolver();
for (int i=0; i<resultado.length; i++)
{%>
<li><%=resultado[i]%></li>
<%}%>

</ol>
<% } else { %>
<h3> no hay suficientes numeros en el intervalo solicitado </h3>
<% } %>
</body>
</html>
Si el valor que pasamos a las propiedades proviene de una variable declarada en un script de jsp,
usaremos el atributo value:
<%@page contentType = "text/html" %>
<html>
<head><title>Numero aleatorio sin repetición</title></head>
<body bgcolor = #AAB42A text = navy>
<%
int supe = Integer.parseInt(request.getParameter("superior"));
int infe = Integer.parseInt(request.getParameter("inferior"));
int canti = Integer.parseInt(request.getParameter("cantidad"));
if (supe - infe >= canti-1){
%>
<jsp:useBean id="objeto" scope="session" class="BeansPropios.BJSPPARAMETROS" />
<jsp:setProperty name="objeto" property="cantidad" value = "<%=canti%>"/>
<jsp:setProperty name="objeto" property="inferior" value = "<%=infe%>"/>
<jsp:setProperty name="objeto" property="superior" value = "<%=supe%>"/>
<font size ="6">Números generados</FONT>
<BLOCKQUOTE>
<ol type = "disc">
<%
int [] resultado = objeto.Devolver();
for (int i=0; i<resultado.length; i++)
{%>
<li><%=resultado[i]%></li>
<%}%>

</ol>
<% } else { %>
<h3> no hay suficientes numeros en el intervalo solicitado </h3>
<% } %>
</body>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</html>

jsp:getProperty
Este elemento devuelve el valor de una propiedad del Bean, lo convierte a un String y lo inserta en
la salida. Los dos atributos requeridos son name, el nombre del Bean previamente referenciado
mediante jsp:useBean, y property. el nombre de la propiedad cuyo valor deseamos obtener. Este
ejemplo aclara un poco más la inserción del parámetro en la página:
<jsp:useBean id="Bean1" ... />
Nombre:
<jsp:getProperty name="Bean1" property="nombre" />
Edad:
<jsp:getProperty name="Bean1" property="edad" />
jsp:forward
Esta acción te permite redirigir la petición a otra página. Tiene un único atributo, page, el cual
contiene una URL relativa. Esta puede ser un valor fijo o ser obtenido en el momento de la petición.
<jsp:forward page="/pagina1.jsp" />
En el siguiente ejemplo enviamos a la página autorizado.html o noautorizado.html dependiendo de
si el usuario tiene o no acceso al portal web.

<html>
<head><title>JSP Page</title></head>
<body>

<jsp:useBean id="objeto" scope="session" class="BeansPropios.Verificar" />


<jsp:setProperty name="objeto" property="usuario" property="usuario" />
<jsp:setProperty name="objeto" property="contra" property="contra" />

<% if(objeto.Esta()){ %>

<jsp:forward page="autorizado.html"/>

<% }else{ %>


<jsp:forward page="noautorizado.html" />

<%}%>

</body>
</html>
jsp:plugin
La acción proporciona fácil apoyo para incluir applets de Java en páginas generadas por
JSP. Es utilizado para generar etiquetas específicas para cada navegador: embed para explorer u
object para netscape) que resultan de la descarga de software Plug-in de Java si fuera preciso.
permite olvidarnos de las diferencias de navegador o de la maquina virtual incorporada a
nuestro navegador.
Componentes de la etiqueta <jsp:plugin>:
<jsp:params>: Permite pasar parámetros al applet.
<jsp:fallback>: Si el plug-in no puede ser lanzado, lo que se incluya en esta etiqueta será lo que
visualicemos
en el navegador del cliente.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%@page contentType="text/html"%>

<HTML>
<head><title>CARGA DE APPLET</TITLE>
</head>

<jsp:plugin type="applet" code="XYZApp.class" width="300" height="300">


<jsp:params>
<jsp:param name="model" value="MODELS\HyaluronicAcid.xyz"/>
</jsp:params>
<jsp:fallback>
<b>Imposible lanzar el Plugin</b>
</jsp:fallback>

</jsp:plugin>

</body>
</HTML>

Ver Video: Desarrollo Páginas JSP, en la Unidad 11,


en el Módulo 5, en la plataforma elearning

Laboratorio: Directivas JSP


Objetivo
Realizar una aplicación que recupere registros de la tabla emp de Oracle y los muestre paginados.
Enunciado:
 Crear una página jsp que permita paginar los registros de los empleados de cinco en cinco,
diez en diez, quince en quince o de veinte en veinte
 Mostrar valores numéricos para poder paginar los registros dependiendo del número de
registros que queden.

Creación de la table emp e inserción de registros:


CREATE TABLE EMP
(EMP_NO NUMBER(4,0)
CONSTRAINT EMP_PRIMARY_KEY PRIMARY KEY,
APELLIDO VARCHAR2(10)
NOT NULL,
OFICIO VARCHAR2(10)
CONSTRAINT EMP_CHK_OFICIO CHECK(OFICIO

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
IN('ANALISTA','DIRECTOR','EMPLEADO','PRESIDENTE','VENDEDOR')),
DIR NUMBER(4,0)
CONSTRAINT EMP_SELF_KEY REFERENCES EMP(EMP_NO),
FECHA_ALT DATE
DEFAULT SYSDATE,
SALARIO NUMBER(10,0)
CONSTRAINT EMP_CHK_SALARIO CHECK(SALARIO BETWEEN 100000 AND 999999),
COMISION NUMBER(10,0),
DEPT_NO NUMBER(2,0)
NOT NULL,
CONSTRAINT EMP_FOREIGN_KEY FOREIGN KEY(DEPT_NO) REFERENCES
DEPT(DEPT_NO)
);

insert into emp values('7839','rey','PRESIDENTE',null,'17-nov-95',650000,null,10);


insert into emp values('7698','negro','DIRECTOR',7839,'01-may-95',370500,null,30);
insert into emp values('7566','jimenez','DIRECTOR',7839,'02-abr-95',386750,null,20);
insert into emp values('7782','cerezo','DIRECTOR',7839,'09-jun-95',318500,null,10);
insert into emp values('7499','arroyo','VENDEDOR',7698,'20-feb-94',208000,39000,30);
insert into emp values('7521','sala','VENDEDOR',7698,'22-feb-95',162500,65000,30);
insert into emp values('7654','martin','VENDEDOR',7698,'29-jul-95',162500,182000,30);
insert into emp values('7844','tovar','VENDEDOR',7698,'08-jul-95',195000,0,30);
insert into emp values('7900','jimeno','EMPLEADO',7698,'03-dic-95',123500,null,30);
insert into emp values('7902','fernandez','ANALISTA',7566,'03-dic-95',390000,null,20);
insert into emp values('7788','gil','ANALISTA',7566,'09-nov-95',390000,null,20);
insert into emp values('7369','sanchez','EMPLEADO',7902,'17-dic-94',104000,null,20);
insert into emp values('7876','alonso','EMPLEADO',7788,'23-jul-95',143000,null,20);
insert into emp values('7934','muñoz','EMPLEADO',7782,'23-ene-96',169000,null,10);

Insertar el siguiente código en la página JSP.


<%@ page contentType="text/html"%>
<%@page import="java.io.*, java.sql.*"%>

<%! int vReg; %>


<%! int vPosicion; %>

<%
if (request.getParameter("registros") != null)
vReg = Integer.parseInt(request.getParameter("registros"));
else
vReg = 5;

if (request.getParameter("posicion") != null)
vPosicion = Integer.parseInt(request.getParameter("posicion"));
else
vPosicion = 1;
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<script language="javascript">

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
function paginar(pNumReg)
{
var vDestino = "paginacion.jsp?registros=" + pNumReg + "&posicion=1";
window.location = vDestino;
}
</script>

<style>
BODY {
text-align: center;
background-color: #EEEEEE;
}
TD, SELECT, OPTION {
background-color: #CCDDFF;
font-size: 12px;
color: #660099;
border: 1px solid #9999CC;
font-family: tahoma;
}
TH {
font-size: 14px;
font-family: arial;
text-align: center;
}
A, A.link, A.visited {
text-decoration: none;
font-size: 12px;
color: #6699CC;
}
A:hover {
color: #660099;
}
.CENTRO {
background-color: #660099;
font-weight: bold;
color: #FFFFFF;
}
</style>
</HEAD>

<BODY>
<table style="border: 1px solid #99CCFF; background-color: #DDDDDD; width: 500px;">
<tr>
<td colspan="3" style="text-align: right; color: #000000; background-color: #FFCC99;">_

registros por pantalla _


<select name="fNumRegistros" style="width: 50px;" onchange="paginar(this.value);">
_
<%

_
for (int i=5; i<=20; i+=5)

_
{

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
if (i == vReg)

_
{

_
%>

_
<option value="<%= i %>" selected> <%= i %> </option>

_
<%

_
}

_
else

_
{

_
%>

_
<option value="<%= i %>">_
<%= i %> </option>

_
<%

_
}

_
}
%>

_
</select>
</td>
</tr>
<tr><td colspan="3" style="background-color: #DDDDDD; border: 0px;"> &nbsp; </td></tr>
<tr>
<th colspan="3"> Listado de empleados </th>
</tr>
<tr>
<td class="CENTRO" style="width: 50px;"> Num. </td>
<td class="CENTRO" style="width: 225px;"> Apellido </td>
<td class="CENTRO" style="width: 225px;"> Puesto </td>
</tr>
<%
Connection vConexion;
Statement vSentencia;
ResultSet vRegistros;

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
String vConsulta;
int vNumReg = 0;

try
{
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
}
catch(Exception e){ System.out.println("Error en la carga del driver..."); }

try
{

vConexion = DriverManager.getConnection
("jdbc:oracle:thin:@Servidor:1521:BdEmpleados","system", "a1b2");

vSentencia =
vConexion.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, _
ResultSet.CONCUR_UPDATABLE);
vConsulta = "SELECT emp_no, apellido, oficio FROM emp ORDER BY
apellido;";
vRegistros = vSentencia.executeQuery(vConsulta);

vRegistros.last();
vNumReg = vRegistros.getRow();
vRegistros.absolute(vPosicion);

for (int i=0; i<vReg && !vRegistros.isAfterLast(); i++)


{
%>
<tr>
<td> <%=vRegistros.getString(1)%> </td>
<td> <%=vRegistros.getString(2)%> </td>
<td> <%=vRegistros.getString(3)%> </td>
</tr>
<%
vRegistros.next();
}

%>
<tr>
<th colspan="3" style="text-align: right;">
<%
for (int p=0, j=1; p <= vNumReg-1; p += vReg, j++)
{
%>
<a
href="paginacion.jsp?registros=<%=vReg%>&posicion=<%=p+1%>">_
<%=j%></a> &nbsp;
<%
}
%>
</th>
</tr>
<%
vConexion.close();
}

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
catch(SQLException e) { System.out.println(e.toString()); }
catch(Exception e) { System.out.println(e.toString()); }
%>

</table>
</BODY>
</HTML>

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 12. Desarrollo de páginas JSP con
etiquetas personalizadas
Objetivos
 Desarrollar aplicaciones encapsulando la funcionalidad dinámica de objetos.
 Definir e implementar cada uno de los archivos que intervienen en un desarrollo con Custom
Tags.

Introducción
Los Custom Tags (etiquetas personalizadas) son un mecanismo para encapsular funcionalidad
dinámica en objetos accedidos a través de extensiones del lenguaje JSP.

Ejemplo de etiqueta propia:


Un mecanismo simple y flexible de tags que permite crear tags propios dentro una
página JSP, que invocan a algún código para realizar una acción.
Eliminación del código de scripts de las JSP.
Separación clara entre el código de la presentación y el de la lógica del negocio.
Los Custom Tags son una extensión del lenguaje JSP. Es un tag XML definido por el programador,
que representa alguna acción o genera contenido dinámico en la JSP. Los custom tags son
distribuídos en librerías de custom tags que definen un conjunto de custom tags relacionados.
Cuando la JSP que contiene un custom tag se traduce a un servlet, el tag se convierte en
operaciones sobre un objeto llamado tag handler. El Contenedor Web invoca a dichas operaciones
cuando el servlet generado a partir de la JSP se ejecuta.
Los custom tags pueden:
 Ser customizados mediante atributos pasados por la JSP
 Acceder a todos los objetos disponibles en la JSP
 Modificar la respuesta generado por la JSP
 Comunicarse entre ellos
 Anidarse

Diseñar una aplicación web con etiquetas


personalizadas
En una aplicación web que utilice etiquetas personalizadas, tendremos que incluir un archivo tld que
defina la información de las etiquetas de nuestro proyecto, un fichero o ficheros java donde

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
implementemos la lógica de negocio de las etiquetas, y por último un fichero XML(web.xml) que
indique la localización del archivo tld.

En el siguiente ejemplo realizaremos una etiqueta básica que muestre información en pantalla:

mensaje.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib PUBLIC


"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>Autor</shortname>
<tag>
<name>primera</name>
<tagclass>etiquetas.Etiqueta1</tagclass>
<bodycontent>empty</bodycontent>

</tag>
</taglib>

TLD (Descriptor de biblioteca de etiquetas).


Elemento raíz
 tlibversion: Es la versión de la implementación de la etiqueta.
 jspversion: Es la versión de la especificación JSP de la que depende la biblioteca de etiqueta.
 shortname: Es el nombre identificativo de la etiqueta, este puede ser utilizado por
herramientas de composición JSP.
 description: Cadena explicativa del funcionamiento de la etiqueta personalizada.
 validator: Puede ser utilizado parra especificar una clase java que se haga referencia en el
periodo de traducción para validar el uso de las etiquetas.
 listener: Integra bibliotecas de etiquetas con el apoyo para eventos de nivel de aplicación.
 Elemento raíz
 name: Nombre que identificará a la etiqueta.
 tag-class: Es el nombre de la clase de manejador de la etiqueta.
 tei-class: Define una sub-clase que proporcionará información extra sobre la etiqueta.
 body-content: Atributo opcional que especifica el tipo de contenido de cuerpo que debe tener
la etiqueta.
Los posibles valores son: JSP(valor por defecto, el contenido de cuerpo de la etiqueta será evaluado
en el periodo de ejecución), tagdependent (la maquina JSP no debe evaluar el contenido) y empty
(cuando la etiqueta no debe tener ningún contenido).

Etiqueta1.java

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
package etiquetas;
import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.TagSupport;

public class Etiqueta1 extends TagSupport {

public int doStartTag() throws JspTagException{

return SKIP_BODY;
}

public int doEndTag() throws JspTagException{

try {
pageContext.getOut().write("Primer ejemplo de Custom Tags");
} catch (IOException ex) {
throw new JspTagException(
"Error");
}
return EVAL_PAGE;
}

Método doStartTag():
Será invocado cuando la máquina JSP encuentre el inicio de una etiqueta implementado por esta
clase.
Valores de retorno:
EVAL_BODY_INCLUDE: Destinado a evaluar el contenido del cuerpo de la etiqueta y cualquier sub-
etiqueta.
SKIP_BODY: Los contenidos de la etiqueta serán ignorados.
Método doEndTag():
Será invocado cuando la máquina JSP encuentre el final de una etiqueta implementado por esta
clase.
Valores de retorno:
EVAL_PAGE: Hará que la máquina JSP evalúe el resto de la página jsp.
SKIP_PAGE: Hará que la máquina JSP no evalúe el resto de la página jsp
web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web


Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<welcome-file-list>
<welcome-file>indice.jsp</welcome-file>
</welcome-file-list>
<taglib>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<taglib-uri>eti</taglib-uri>
<taglib-location>/WEB-INF/etiquetas/mensaje.tld</taglib-location>
</taglib>
</web-app>

indice.jsp
<%@ taglib uri="eti" prefix="MiEtiqueta" %>
<html>
<head>
<title>Primer TAG</title>
</head>
<body>
<MiEtiqueta:primera/>
</body>
</html>

Etiquetas con atributos


Los Custom Tags pueden tener atributos, estos atributos deben ser definidos en el tld para poder ser
implementados.
En el ejemplo siguiente incorporamos un atributo llamado nombre a la etiqueta del ejemplo anterior.

mensaje.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>


<!DOCTYPE taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>Autor</shortname>
<tag>
<name>primera</name>
<tagclass>etiquetas.Etiqueta1</tagclass>
<bodycontent>empty</bodycontent>
<attribute>
<name>nombre</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
Etiqueta1.java
package etiquetas;

import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.TagSupport;

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public class Etiqueta1 extends TagSupport {

private String nombre;


public String getNombre(){
return nombre;
}

public void setNombre(String nombre){


this.nombre=nombre;
}

public int doStartTag() throws JspTagException{

return SKIP_BODY;
}

public int doEndTag() throws JspTagException{


try {
pageContext.getOut().write("Hola "+ getNombre());

} catch (IOException ex) {


throw new JspTagException(
"Error");
}
return EVAL_PAGE;
}
}
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web


Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<welcome-file-list>
<welcome-file>indice.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>eti</taglib-uri>
<taglib-location>/WEB-INF/etiquetas/mensaje.tld</taglib-location>
</taglib>
</web-app>
indice.jsp
<%@ taglib uri="eti" prefix="MiEtiqueta" %>

<html>
<head>
<title>Primer TAG</title>
</head>

<body>

<MiEtiqueta:primera nombre="pepe"/>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</body>
</html>
Mostrará en pantalla el mensaje:

Etiquetas con contenido en el cuerpo


La implementación de default devuelve SKIP_BODY, por lo tanto el cuerpo del tag será procesado solamente una
vez.

En el ejemplo siguiente incorporamos información en el cuerpo.


mensaje.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>Autor</shortname>
<tag>
<name>primera</name>
<tagclass>etiquetas.Etiqueta1</tagclass>
<bodycontent>JSP</bodycontent>
</tag>
</taglib>
Etiqueta1.java
package etiquetas;

import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.TagSupport;

public class Etiqueta1 extends TagSupport {

public int doStartTag() throws JspTagException{

return EVAL_BODY_INCLUDE;
}

public int doEndTag() throws JspTagException{


String dateString = new Date().toString();
try {
pageContext.getOut().write("Hola <br/>" );

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
} catch (IOException ex) {
throw new JspTagException(
"Error");
}
return EVAL_PAGE;
}

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web


Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<welcome-file-list>
<welcome-file>indice.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>eti</taglib-uri>
<taglib-location>/WEB-INF/etiquetas/mensaje.tld</taglib-location>
</taglib>
</web-app>
indice.jsp
<%@ taglib uri="eti" prefix="MiEtiqueta" %>
<html>
<head>
<title>Primer TAG</title>
</head>
<body>

<MiEtiqueta:primera>
Nombre del cliente:
<%String nombre="Pepe ";%>
<%String Apellido="Ramos";%>
<%=nombre%><%=Apellido%><br/>
</MiEtiqueta:primera>
</body>
</html>
Resultado:

Utilizar etiquetas JSTL en una página JSP


Core

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
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

Ejemplo:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<c:out value="Hola mundo"/><br/>
<c:out value="${variableInexistente}" default="La expresión fallo"/><br/>
<c:out value="${variableInexistente}">
Por defecto el atributo default va en el cuerpo
</c:out>

c:set
Atributo Descripción Requerido Por
defecto
value Información a grabar. no cuerpo
target Nombre de la variable cuya propiedad será modificada no ninguno
property Propiedad a modificar no ninguna
var Nombre de la variable en la que guardar. no ninguno
scope Ámbito de la variable en la que grabar la información (page, no page
request, session, o application)

Ejemplos:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%-- 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>
c:remove
Atributo Descripción Requerido Por defecto
var Nombre de la variable a quitar. sí --
scope Ámbito de la variable a quitar. no todos los ámbitos

c:if
Atributo Descripción Requerido Por

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
defecto
test Condición a evaluar. Solo procesa el cuerpo si es true. sí --
var Nombre del atributo con el que grabar el resultado booleano de no ninguno
la condición.
scope Ámbito en el que exponer el atributo anterior. no page

En el cuerpo es posible colocar otras etiquetas, incluyendo otras Es útil guardar el resultado
de evaluar la condición para evitar repetir los cálculos.

c:choose, c:when, c:otherwise

No tiene atributos. Acepta como hijos uno o más

<c:when> tiene un atributo:


<c:otherwise> no tiene atributos.

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:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<c:set var="hour" value="${18}"/>
<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.
Es posible anidar varias etiquetas c:forEach.
Atributo Descripción Requerido Por
defecto
items Colección sobre la que iterar. no ninguno
begin Elemento con el que empezar (0=primero). no 0
end Elemento con el que terminar (0=primero). no último
step Procesa solo cada step elementos. no 1 (todos)
var Nombre del atributo con el que exponer el elemento actual. no ninguno
varStatus Nombre de la variable con la que exponer el estado de la no ninguno
iteración.

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


Atributo Tipo Requerido
begin número El valor del atributo begin.
current número El elemento actual.
end número El valor del atributo end.
index número Índice del elemento actual dentro de la colección.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
count número Número de iteración (empezando en 1).
first boolean Indica si estamos en la primera iteración.
last boolean Indica si estamos en la última iteración.
step número El valor del atributo step.

Si se omite el atributo items, se itera sobre números:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<c:forEach begin="1" end="24" step="1" var="HORA" varStatus="status">
<c:out value="${HORA}"/>
<c:if test="${status.count == 15}">Comienza clase de Java</c:if>
<c:if test="${status.count == 19}">Fin de clase de Java</c:if>
<br/>
</c:forEach>
c:forTokens
Permite descomponer una cadena en tokens.
Atributo Descripción Requerido Por defecto
items Cadena sobre la que iterar sí ninguno
delims Caracteres delimitadores sí ninguno
var Nombre del atributo con el que exponer el token actual no ninguno

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.
Atributo Descripción Requerido Por defecto
url URL para importar la página. Es válido sí --
cualquier protocolo soportado por
java.net.URL. Es decir, al menos HTTP,
HTTPS, FTP, file, y JAR.
context Barra (/) seguido del nombre de la no contexto actual
aplicación local
var Nombre del atributo con el que exponer no muestra en página
el texto importado.
scope Ámbito del atributo anterior. no page
charEncoding Juego de caracteres con el que importar no ISO-8859-1
los datos.
varReader Nombre de una variable con la que no ninguno
exponer el java.io.Reader con que se lee
la URL.

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

Atributo Descripción Requerido Por defecto


name nombre del parametro sí --
value valor del parametro no cuerpo

c:redirect

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
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
Atributo Descripción Requerido Por defecto
url URL a la que redirigir. sí --
context Barra (/) seguido del nombre de una no contexto actual
aplicación local.

Ejemplo:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<c:redirect url="paginarecuperar.jsp"/>
c:url
Sirve para mostrar una URL o para grabarla en una variable. Sus atributos son:
Atributo Descripción Requerido Por defecto
value Base URL a mostrar o almacenar. sí --
context Barra (/) seguido del nombre de una no contexto
aplicación local. actual
var Nombre del atributo en el que exponer no ningúno
la URL.
scope Ámbito del atributo anterior. no page

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.
Atributo Descripción Requerido Por defecto
var Variable para exponer información no ninguno
sobre el error.

IGUAL QUE CON JSP, al estar controlado el error en la página actual no se va a error.jsp.

<%@ page errorPage="error.jsp" %>


<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<c:catch var="error">
<fmt:parseNumber var="total" value="FDJ34rm4"/>
<%-- nunca llega aquí --%>
...
</c:catch>
<c:if test="${not empty error}">
Introduzca números.<br/>
Detalles del error: <c:out value="${error}"/>
</c:if>
SIN CONTROLAR EL ERROR:

<%@ page errorPage="error.jsp" %>


<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
<fmt:parseNumber var="total" value="FDJ34rm4"/>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%-- nunca llega aquí --%>
...
<c:if test="${not empty error}">
Introduzca números.<br/>
Detalles del error: <c:out value="${error}"/>
</c:if>

error.jsp
<%@ page isErrorPage="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
</html>
<head>Incidencia en el sistema</head>
<body>
El error fue..<br/>
<c:out value="${pageContext.exception.message}"/>
</body>
</html>

Base de Datos
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>
sql:DataSource
Atributo Descripción Requerido Por defecto
dataSource Base de datos a usar. no ningúno
driver Nombre de la clase JDBC a no ningúno
usar como driver.
url URL de la base de datos. no ningúno
user Nombre del usuario de la base no ningúno
de datos.
password Password del usuario de la no ningúno
base de datos.
var Nombre de la variable que no ningúno
representa la base de datos.
scope Ámbito de la variable anterior. no page

Ejemplos:
MYSQL
<sql:setDataSource driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"
user="alicia" password="secreto"/>
ORACLE

<sql:setDataSource driver="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@maquina:puerto:instancia"
…………………
PUENTE JDBC-ODBC
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"
url="jdbc:odbc:nombreDsn;UID=uid;PWD=password"
................

Creamos un dataSource y lo guardamos en una variable:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<sql:setDataSource driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test"
user="alicia"
password="secreto"
var="development1"/>

<sql:setDataSource dataSource="${development1}"
scope="request" />

EJEMPLO CON NUESTRA BD DE EMPLEADOS:


<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"url="jdbc:odbc:java_jstl;UID=sa"/>

sql:query
Cualquier consulta de selección (no de acción) sobre la base de datos usaremos sql:query,
previamente tendremos creado un sql:setDataSource.

Esta etiqueta no muestra datos, solo los graba en la variable indicada por var.
Atributo Descripción Requerido Por
defecto
sql Consulta SQL a ejecutar. no si ponemos el SQL en el cuerpo
cuerpo de la etiqueta
dataSource Proveedor de conexiones. no
startRow Primeras filas a ignorar (ej: 10=ignora no 0
las diez primeras filas). (primero)
maxRows Máximo número de filas. no
var Variable con la que exponer el sí ningúno
resultado.
scope Ámbito de la anterior variable. no page

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.
Las propiedades disponibles son:
columnNames: 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.
Ejemplos:
<sql:query var="empleados">
SELECT * FROM emp
</sql:query>
Forma equivalente a la anterior:
<sql:query var="empleados" sql="SELECT * FROM USERS"/>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Suponiendo que el SQL este en una variable:
<sql:query var="empleados" sql="${sql}"/>
EJEMPLO, VISUALIZAR APELLIDO Y SALARIO DE TODOS LOS EMPLEADOS:

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"url="jdbc:odbc:java_jstl;UID=sa"/>
<sql:query var="Empleados">
SELECT apellido,salario FROM emp
</sql:query>
<ul>
<c:forEach items="${Empleados.rows}" var="row">
<li>
<c:out value="${row.apellido}"/> -
<c:out value="${row.salario}"/>
</li>
</c:forEach>
sql:update
Cualquier consulta de acción(no de selección) sobre la base de datos usaremos sql:update,
previamente tendremos creado un sql:setDataSource.
Atributo Descripción Requerido Por defecto
sql consulta SQL a ejecutar no cuerpo
dataSource proveedor de conexiones no
var variable para guardar el número de no ningúno
filas actualizadas
scope ámbito de la anterior variable no page

Ejemplo borrar al empleado tovar de nuestra base de datos:

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"url="jdbc:odbc:java_jstl;UID=sa"/>
<sql:update var="n">
DELETE FROM empleados
WHERE apellido = ‘pepe’
</sql:update>
Hemos borrado <c:out value="${n}"/> filas.

sql:param
Utilizado para las consultas preparedStatement, pasar parámetros (?) a consultas preparadas para
ello.
La etiqueta sql:param sustituirá los caracteres ? de las sentencias SQL. Los caracteres ? únicamente
pueden usarse para sustituir un valor (string o número).
No válido para fechas.
Atributo Descripción Requerido Por defecto
value valor del parámetro no cuerpo

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>


<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>

<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver"url="jdbc:odbc:java_jstl;UID=sa"/>

<c:set var="p_deptno" value="11"/>


<c:set var="p_loc" value="Valencia"/>
<c:set var="p_dnombre" value="Marketing"/>

<sql:update var="ni">
INSERT INTO departamentos VALUES(?,?,?)
<sql:param value="${p_deptno}"/>
<sql:param value="${p_loc}"/>
<sql:param value="${p_dnombre}"/>
</sql:update>

Hemos insertado <c:out value="${ni}"/> filas.


sql:dateParam
Atributo Descripción Requerido Por defecto

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
value fecha a sustituir en sí --
el carácter ?
type time, date, o no timestamp
timestamp

Ejemplo:

<sql:query>
SELECT * FROM emp
WHERE fecha_alt < ?
<sql:dateParam value="${p_fecha}"/>
</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.
Ejemplo intentar duplicar registros:
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql_rt"%>
<sql:setDataSource driver="sun.jdbc.odbc.JdbcOdbcDriver" url="jdbc:odbc:java_jstl;UID=sa"
var="ORIGEN_EMPLEADOS"/>
<sql:transaction dataSource="${ORIGEN_EMPLEADOS}">
<sql:update>
insert into dept values(11,'Valencia','Astronauta')
</sql:update>
<sql:update>
insert into dept values(11,'Valencia','Astronauta')
</sql:update>
</sql:transaction>
ERROR: No se insertará ninguno de los dos registros, se deshacen las dos consultas.
Formateo
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>
fmt:formatNumber
Funciona como c:out pero permitiendo más control sobre el formato.

Atributo Descripción Requerid Por defecto


o
value Valor numérico a formatear. no cuerpo
type Si mostrar números, monedas, o no number
porcentajes. (puede ser
number,
currency, o
percent)
currencyCode Código de moneda ISO-2417.Solo no ningúno
funciona en JDK1.4 o superior.
currencySymb Símbolo de la moneda (por ejemplo no ningúno
ol $).
groupingUsed Si agrupar o no los dígitos antes del no true
punto decimal.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
maxIntegerDi Máximo número de dígitos a no ningúno
gits mostrar.
minIntegerDig Mínimo número de dígitos a no ningúno
its mostrar.
maxFractionDi Máximo número de dígitos no ningúno
gits fraccionarios a mostrar.
minFractionDi Mínimo número de dígitos no ningúno
gits fraccionarios a mostrar.
pattern Patrón con el formateo del número. no ningúno
Sigue la convención de
java.util.DecimalFormat.
var Variable en la que grabar el no ningúno
resultado.
scope Ámbito de la anterior variable. no page

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
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}"/>
Atributo Descripción Requerido Por defecto
value Fecha a mostrar. sí ningúno
type Si mostrar fechas, horas o ambos. no date (puede
ser date,
time, o both)
dateStyle Estilo preferido para la fecha. no default
(puede ser
default,
short,
medium,
long)
timeStyle Estilo preferido para el tiempo. no default
(puede ser
default,
short,
medium,
long)
timeZone Zona horaria usada para formatear no http://www.t
la fecha. imeanddate.
com
/library/abbr
eviations/tim
ezones/
pattern Patrón de formateo. no Ninguno. Ver
SimpleDateF
ormat.
var Variable en la que grabar el no ningúno
resultado.
scope Ámbito en el que grabar la variable no page
anterior.

El atributo pattern sigue la convención fijada para la clase SimpleDateFormat:


Caracter Descripción Ejemplo
yy Año corto. 02
yyyy Año completo. 2002
M Número del més. 4
MM Número de més con dos dígitos. 04
MMM Nombre corto del més. Apr
MMMM Nombre del més. April
d Día del mes. 5
dd Día del més con dos dígitos. 05
EE Nombre corto del día. Fri
EEEE Nombre del día. Friday
H Hora en formato militar. 21
HH Hora en formato militar con dos 21
dígitos.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
h Hora (1-12). 9
hh Hora (1-12) con dos dígitos. 09
m Minuto. 4
mm Minuto con dos dígitos. 04
s Segundo. 6
ss Segundo con dos dígitos. 06
S Milisegundo. 249
a AM / PM PM
zz Nombre corto de zona horaria. EST
zzzz Zona horaria. Eastern Standard Time
Z Descripción de zona horaria. -0500
'cadena' Cadena a incluir. 'cadena'

Ejemplos de patrones:

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

fmt:parseNumber
Interpreta cadenas como números. Es necesario para pasar valores numéricos a algunas etiquetas
como sql:param, fmt:formatNumber, y otras.
Atributo Descripción Requerido Por defecto
value Cadena a interpretar como no cuerpo
número.
type Como interpretarlo. no number (puede ser number, currency, o
percent)
integerOnly Si descartar decimales. no false
pattern Patrón de formato. no ningúno. Ver SimpleDateFormat.
parseLocale Locale a usar. no
var Variable en la que grabar el no ningúno
resultado.
scope Ámbito de la variable anterior. no page

fmt:parseDate
Interpreta cadenas como fechas.

Atributo Descripción Requerido Por defecto

value Fecha a mostrar. no cuerpo

Si mostrar fechas, horas o


type no date
ambos.

dateStyle Estilo preferido para la fecha. no default (puede ser default, short,

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Atributo Descripción Requerido Por defecto
medium, long)

default (puede ser default, short,


timeStyle Estilo preferido para el tiempo. no
medium, long)

Zona horaria usada para


timeZone no Ningúno. Posibles valores.
formatear la fecha.

pattern Patrón de formateo. no Ningúno. Ver SimpleDateFormat.

parseLocale Locale a usar. no

Variable en la que grabar el


var no ningúno
resultado.

Ámbito en el que grabar la


scope no page
variable anterior.

fmt:setTimeZone
Permite cambiar la zona horaria:

Atributo Descripción Requerido Por defecto


Identificador de la zona Ninguno.
value horaria, o instancia de sí http://www.timeanddate.com
java.util.TimeZone. /library/abbreviations/timezones/
Variable en la que
var no ningúno
guardar la zona horaria.
scope Ámbito de la variable. no page

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.

Atributo Descripción Requerido Por defecto

Ningúno.
Identificador de la zona http://www.timeanddate.com
value sí
horaria. /library/abbreviations/timezon
es/

Ver Video: Etiquetas JSTL con JSP, en la Unidad 12,


en el Módulo 5, en la plataforma elearning

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Laboratorio: Contador de visitas con Custom Tags.
Objetivo
Creación de una etiqueta personalizada.
Enunciado
Realizar una aplicación JSP que incluya un contador de visitas realizado con Customs Tags.

Contador.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib PUBLIC


"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.2</jspversion>
<shortname>Benito Floro</shortname>
<tag>
<name>primera</name>
<tagclass>etiquetas.Contador</tagclass>
<bodycontent>empty</bodycontent>
</tag>
</taglib>

Web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web


Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<welcome-file-list>
<welcome-file>indice.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>contador</taglib-uri>
<taglib-location>/WEB-INF/etiquetas/contador.tld</taglib-location>
</taglib>
</web-app>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Contador.java
package etiquetas;

import java.io.*;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import javax.servlet.http.HttpServletRequest;

public class Contador extends TagSupport {


private int veces;
private File archivo;

public int doStartTag() throws JspException {


try {
ComprobarFichero();//si no existe lo crea
LeerFichero();//
pageContext.getOut().print( ++veces );//escribo en el jsp
}
catch( IOException ioe ) {
throw new JspException( ioe.getMessage() );
}
return SKIP_BODY;//xa saltar el contenido si hay algo despues de la etiqueta
}

public int doEndTag() throws JspException {//cuando termina la etiqueta


Guardar();
return EVAL_PAGE;//xa q continue evaluando despues del final de la etiqueta
}

private void ComprobarFichero() throws JspException, IOException {


if( archivo == null ) {
archivo = new File( getNombre() );
veces = 0;
}
if( !archivo.exists() ) {
archivo.createNewFile();
Guardar();
}
}

private String getNombre() {


HttpServletRequest peticion = ( HttpServletRequest
)pageContext.getRequest();//quien ha pedido la pagina
String servletPath = peticion.getServletPath();//path donde esta el servlet que me
ha hecho la peticion
String path = pageContext.getServletContext().getRealPath( servletPath
);//construyo un path real respecto a servletPath
return path + ".cont";//extension del fichero que se va a crear
}

private void Guardar() throws JspException {


try {
FileWriter escritor = new FileWriter( archivo );
escritor.write( veces );

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
escritor.close();
}
catch( Exception e ) {
throw new JspException( e.getMessage() );
}
}

private void LeerFichero() throws JspException {


try {
FileReader lector = new FileReader( archivo );
veces = lector.read();
lector.close();
}
catch( Exception e ) {
throw new JspException( e.getMessage() );
}
}
}

indice.jsp
<HTML>
<HEAD>
<TITLE>Etiqueta contador</TITLE>
</HEAD>
<BODY bgcolor="navy" text="white">
<%@ taglib uri="contador" prefix="prueba" %>
<H1>La página ha sido visitada <prueba:primera /> veces.</H1>
</BODY>
</HTML>

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 13. Desarrollo de Aplicaciones Web
con la Clase ActionForm de Struts
Objetivos
 Trabajar con la clase ActionForm de Struts
 Desarrollar aplicaciones Struts con una clase que herede de Action Form.

Introducción
El marco de trabajo Struts generalmente asume que hemos definido un bean ActionForm por cada
formulario de entrada necesario en nuestra aplicación. Los beans ActionForm algunas veces son sólo
llamados "beans formuLario". Si declaramos dichos beans en nuestro fichero de configuración
ActionMapping , el servlet controlador Struts realiza automáticamente los siguientes servicios por
nosotros, antes de llamar al método Action apropiado:
Chequea en la sesión de usuario si hay un ejemplar de un bean de la clase apropiada, bajo la clave
apropiada.
Si no está disponible dicho bean en el ámbio de la sesión, se crea uno nuevo automáticamente y se
añade a la sesión de usuario.
Por cada parámetro de la solicitud cuyo nombre corresponda con el nombre de una propiedad del
bean, se llamará al correspondiente método set(). Esto opera de una forma similar a la acción JSP
estándard cuando usamos el comodín asterisco para seleccionar todas las propiedades.
El bean ActionForm actualizado será pasado al método perform() de la clase Action cuando es
llamado, haciendo que esos valores estén disponibles inmediatamente.
Cuando codifiquemos nuestros beans ActionForm, debemos tener en mente los siguientes principios:
La propia clase ActionForm no requiere que se implemente ningún método específico. Se usa para
identificar el rol que esos beans particulares juegan en la arquitectura general. Normalmente, un
bean ActionForm sólo tendrá metodos setxxx() y getxxx(), sin lógica de negocio.
El objeto ActionForm también ofrece un mecanismo de validación estándard. Si sobreescribimos un
método "stub", y proporcionamos mensajes de error en el recurso de aplicación estándard, Struts
validará automáticamente la entrada del formualrio (usando nuestro método). Ver Validación del
Formulario para más detalles. Por supuesto, también podemos ignorar la validación de ActionForm y
proporcionar nuestro propio objeto Action.
Definir una propiedad (asociada con métodos getXxx() y setXxx()) para cada campo que esté
presente en el formulario. El nombre del campo y el nombre de la propiedad deben corresponder de
acuerdo a las convenciones usuales de los JavaBeans. Por ejemplo, un campo de entrada llamado
username hará que se llame al método setUsername().
Debemos pensar en nuestros beans ActionForm como firewall ente HTTP y el objeto Action. Usamos
el método validate para asegurarnos de que están presentes todas las propiedades requeridas, y
que contienen valores razonables. Un ActionForm que falla en la validación incluso ni será
presentado para el manejo del Action.
También podríamos situar un ejemplar bean en nuestro formulario, y usar referencias a propieades
anidadas. Por ejemplo, podríamos tener un bean "customer" en nuestro Action Form, y luego
referirnos a la propiedad "customer.name" en nuestra vista JSP. Esto correspondería con los
métodos customer.getName() y customer.setName(string Name) de nuestro bean customer.
Si anidamos ejemplares de beans existentes en nuestro formulario, debemos pensar en las
propiedades que exponemos. Cualquier propiedad pública en un ActionForm que acepta un simple
valor String puede seleccionarse con un string de consulta. Podría ser muy útil situar dichos beans
dentro de una fina "envoltura" que exponga sólo las propiedades requeridas. Esta envoltura también

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
puede proporcionar un filtro para asegurarnos en tiempo de ejecución de que las propiedades no se
seleccionan con valores inapropiados.
Deberías haber observado que un "formulario", en el sentido discutido aquí, no corresponde
necesariamente con una sóla página JSP en el interface de usuario. Es común en muchas
aplicaciones tener un "formulario" (desde la perspectiva del usuario) que se extienda sobre múltiples
páginas. Piensa por ejemplo, en un interface de usuario al estilo de los wizard que se utilizan
comunmente cuando instalamos nuevas aplicaciones. Struts nos aconseja definir un sólo ActionForm
que contenga las propiedades de todos los campos, sin importar que página de campo se está
mostrando actualmente. De igual forma, las distintas páginas del mismo formulario deberían ser
reenvidas a la misma clase Action. Si seguimos estas sugerencias, los diseñadores de páginas
podrán reordenar los campos entre varias páginas, frecuentemente sin requerir que cambiemos la
lógica de procesamiento.
Clase ActionForm creada con NetBeans

Crear una clase ActionForm


Las subclases del JavaBean ActionForm representan a datos compartidos entre la vista y las
subclases de los objetos de tipo Action.
Las subclases de ActionForm se utilizan para validar los datos introducidos por el usuario en la
vista (en nuestro caso una página JSP) para ello se utilizan dos métodos de la Clase ActionForm:
reset() - inicializa las variables de instancia de las subclases de ActionForm
validate() - comprueba que todos los datos introducidos por el usuario son correctos. Si algún dato no
es correcto se añade un mensaje de error a un objeto de tipo ActionErrors propagar los datos
introducidos en la vista a una subclase de un objeto de tipo Action
Las subclases de ActionForm son como cortafuegos entre los usuarios y las subclases de objetos
de tipo Action
Las subclases de ActionForm no deberían tener código relacionado con la lógica de negocio.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
En el fichero struts-config.xml el asistente de NetBeans ha añadido el elemento
<form-bean>
<struts-config>
<form-beans>
<form-bean name="TiendaActionForm" type="pqActionForms.TiendaActionForm"/>
</form-beans>

Modificamos el fichero TiendaActionForm para incuir las propiedades nombre y apellido, además de
controlar que el campo nombre y apellido no se queden en blanco.
package pqActionForms;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

public class TiendaActionForm extends org.apache.struts.action.ActionForm {

private String nombre;


private String apellido;

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public String getApellido() {


return apellido;
}

public void setApellido(String apellido) {


this.apellido = apellido;
}

public TiendaActionForm() {
super();
}

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
ActionErrors errors = new ActionErrors();
if (getNombre() == null || getNombre().length() < 1) {
errors.add("nombre", new ActionMessage("error.nombre.requerido"));
}
if (getApellido() == null || getApellido().length() < 1) {
errors.add("apellido", new ActionMessage("error.apellido.requerido"));
}
return errors;
}
}
ApplicationResource.propierties
error.nombre.requerido=Nombre obligatorio
error.apellido.requerido=Apellido obligatorio
Creación de un proyecto mvc con struts
TiendaForm.jsp
En esta página insertaremos etiquetas de la librería de Struts Html para rellenar un formulario y
controlar que los datos que se introduzcan sean válidos.

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

<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>


<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>

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

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<title>JSP Page</title>
</head>
<body>

<html:form action="Tienda">

<div style="left: 210px; top: 10px; font-size: 24px;


font-weight: bold; position: absolute">
<bean:message key="literal.bienvenida" />
</div>
<div style="left: 250px; top: 40px; font-size: 10px; position: absolute">
*<bean:message key="literal.mensajeEnvios" />
</div>

<div style="left: 28px; top: 80px; position: absolute">


<bean:message key="literal.nombre" />*
</div>
<div style="left: 28px; top: 100px; position: absolute">
<html:text property="nombre" size="40" />
</div>
<div style="left: 28px; top: 123px; position: absolute">
<html:errors property="nombre" />
</div>

<div style="left: 320px; top: 80px; position: absolute">


<bean:message key="literal.apellido" />*
</div>
<div style="left: 320px; top: 100px; position: absolute">
<html:text property="apellido" size="40" />
</div>
<div style="left: 320px; top: 123px; position: absolute">
<html:errors property="apellido" />
</div>

<div style="left: 230px; top: 440px; position: absolute">


<html:reset>
<bean:message key="literal.restaurar" />
</html:reset>
</div>
<div style="left: 320px; top: 440px; position: absolute">
<html:submit>
<bean:message key="literal.enviar" />
</html:submit>
</div>
</html:form>
</body>
</html>
ApplicationResource.properties
literal.bienvenida=Bienvenido a la tienda oficial
literal.mensajeEnvios=Selecciona si tu envío es dentro de España o Internacional
literal.nombre=Nombre
literal.apellido=Apellido
error.nombre.requerido=Nombre obligatorio
error.apellido.requerido=Apellido obligatorio
literal.enviar=Enviar
literal.restaurar=Restaurar

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
errors.header=
errors.prefix=<span style="font-size: 10px; color: red" >
errors.suffix=</span>
errors.footer=
TiendaActionForm
Modificamos el fichero TiendaActionForm para incuir las propiedades nombre y apellido, además de
controlar que el campo nombre y apellido no se queden en blanco.
package pqActionForms;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

public class TiendaActionForm extends org.apache.struts.action.ActionForm {

private String nombre;


private String apellido;

public String getNombre() {


return nombre;
}

public void setNombre(String nombre) {


this.nombre = nombre;
}

public String getApellido() {


return apellido;
}

public void setApellido(String apellido) {


this.apellido = apellido;
}

public TiendaActionForm() {
super();
}

public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {


ActionErrors errors = new ActionErrors();
if (getNombre() == null || getNombre().length() < 1) {
errors.add("nombre", new ActionMessage("error.nombre.requerido"));
}
if (getApellido() == null || getApellido().length() < 1) {
errors.add("apellido", new ActionMessage("error.apellido.requerido"));
}
return errors;
}
}

TiendaAction
Esta clase sería la encargada de recoger los datros del formulario e insertarlos en la base de datos:
public ActionForward execute(ActionMapping mapping, ActionForm form,

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
HttpServletRequest request, HttpServletResponse response)
throws Exception {

// En este método recogeríamos los datos con el objeto HttpServletRequest

return mapping.findForward(SUCCESS);

Ver Video: Internacinalizar Aplicación Struts, en la Unidad 13,


en el Módulo 5, en la plataforma elearning

Laboratorio: Internacionalizar una aplicación


Objetivo
Comprender el funcionamiento de la internacionalización de aplicaciones con Struts.
Enunciado
Desarrollar un sitio web donde el usuario pueda elegir el idioma de visualización del contenido de la
página.
Tendremos una página jsp con tres hipervínculos: Español, inglés y Registro de Usuario/ User
registry.
Al seleccionar español o inglés enviaremos la información sobre la propia página jsp, mostrando los
textos de los hipervínculos en inglés o español.

ESPAÑOL:

INGLÉS:

SeleccionarIdioma.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"
import="org.apache.struts.Globals, java.util.Locale"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"


"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>

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

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
<title>JSP Page</title>
</head>

<body bgcolor="#FF2400">
<%
Locale locale = null;

String strIdioma = request.getParameter("idioma");


if (strIdioma != null) {
if (strIdioma.equals("en")) {
System.out.println("equals en");
locale = new Locale("en");
session.setAttribute(Globals.LOCALE_KEY, locale);
} else if (strIdioma.equals("es")) {
System.out.println("equals es");
locale = new Locale("es");
session.setAttribute(Globals.LOCALE_KEY, locale);
}
}
%>

<div style="left: 70px; top: 50px; position: absolute; font-size: 12px;">


<html:link href="SeleccionarIdioma.jsp?idioma=es">
<bean:message key="literal.cambiarIdioma.español" />
</html:link>
|
<html:link href="SeleccionarIdioma.jsp?idioma=en">
<bean:message key="literal.cambiarIdioma.ingles" />
</html:link>
</div>

<div style="left: 70px; top: 80px; position: absolute;font-size: 16px;">


<html:link action="">
<bean:message key="literal.registroUsuario" />
</html:link>
</div>
</body>
</html>

ApplicationResource.properties
literal.cambiarIdioma.español=Español
literal.cambiarIdioma.ingles=Ingles
literal.registroUsuario=Registro de usuario
ApplicationResource_en.properties
literal.cambiarIdioma.español=Spanish
literal.cambiarIdioma.ingles=English
literal.registroUsuario=User registry

Actividades
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 14. Construcción de Componentes de
Presentación Web Reutilizables
Objetivos
 Uso de la capa de presentación en desarrollos Struts
 Desarrollar aplicaciones utilizando Struts Tiles.

Introducción
La librerías de Stuts que podemos utilizar en la presentación se describen a continuación:
struts-tiles:
Contiene etiquetas que definen un mecanismo de plantillas.
struts-bean:
Contiene etiquetas útiles para acceder a los beans y sus propiedades, así como para definir nuevos
beans que son accesibles para el resto de la página mediante variables de scripting y atributos de
ámbito de página.
struts-html:
Contiene etiquetas para crear formularios de entrada struts, así como otras etiquetas generalmente
útiles en la creación de interfaces de usuario basados en HTML.
struts-logic:
Contiene etiquetas que son útiles para manejar la generación condicional de salida de texto, hacer
bucles sobre colecciones de objetos para generación repetitiva de salida de texto y control del flujo
de la aplicación.

Apreciamos en la imagen como en un proyecto Struts se agregan las TLD de las librerías de
etiquetas de Struts.
La librería struts-bean contiene etiquetas útiles para acceder a los beans y sus propiedades, así
como para definir nuevos beans (basados en esos accesores) que son accesibles para el resto de la
página mediante variables de scripting y atributos de ámbito de página. También se proporcionan
mecanismos convenientes para crear nuevos beans basados en el valor de una cookie, de las
cabeceras y de los parámetros.
La librería struts-html contiene etiquetas para crear formularios de entrada struts, así como otras
etiquetas generalmente útiles en la creación de interfaces de usuario basados en HTML.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
La librería struts-logic contiene etiquetas que son útiles para manejar la generación condicional
de salida de texto, hacer bucles sobre colecciones de objetos para generación repetitiva de salida de
texto y control del flujo de la aplicación.
La librería struts-template contiene etiquetas que definen un mecanismo de plantillas.
Abajo podemos ver cómo se definirían todas las librerías de etiquetas para usarlas en nuestra
aplicación, en realidad, sólo deberíamos especificar las librerías que vayamos a utilizar:
<taglib>
<taglib-uri>
/WEB-INF/struts-bean.tld
</taglib-uri>
<taglib-location>
/WEB-INF/struts-bean.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>
/WEB-INF/struts-html.tld
</taglib-uri>
<taglib-location>
/WEB-INF/struts-html.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>
/WEB-INF/struts-logic.tld
</taglib-uri>
<taglib-location>
/WEB-INF/struts-logic.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>
/WEB-INF/struts-template.tld
</taglib-uri>
<taglib-location>
/WEB-INF/struts-template.tld
</taglib-location>
</taglib>

Tipos de Campos de Entrada Soportados


Struts define etiquetas HTML para todos estos tipos de campos de entrada:
checkboxes
Campos hidden
Campos de entrada password
Botones de radio
Botones de reset
Lsitas select con opciones embebidas o ítems de opciones.
option
options
Botones submit

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Campos de entrada de texto text
textareas
En cada caso, una etiqueta de campo debe estár anidada dentro de una etiqueta form, por eso los
campos saben qué bean utilizar para inicializar los valores mostrados.

Otras Útiles Etiquetas de Presentación


Hay varias etiquetas útiles para crear presentaciones:
[logic] iterate repite su cuerpo de etiqueta una vez por cada elemento de una colección especificada
(que puede ser una Enumeration, un Hashtable, un Vector, o un array de objetos).
[logic] present dependiendo del atributo que se especifique, esta etiqueta chequea la solicitud
actual, y evalua el contenido de los campos anidados de esta etiqueta sólo si hay un valor presente.
Sólo se puede usar uno de los atributos en una ocurrencia de esta etiqueta, a menos que utilicemos
el atributo property, en cuyo caso también es necesario el nombre del atributo. Los atributos
incluyen cookie, header, name, parameter, property, role, scope, y user.
[logic] notPresent el contrario de la etiqueta present, notPresent proporciona la misma funcionalidad
pero cuando el atributo especificado no está presente.
[html] link genera un elemento HTML como una definición de un enlace o un hiperenlace a la
URL especificada, y automáticamente aplica codificación URL para mantener el estado de la sesión
en la ausencia del soporte de cookies.
[html] img genera un elemento HTML con la habilidad de modificar dinámicamente las URLs
especificadas por los atributos "src" y "lowsrc" de la misma forma en que se puede hacer con

[bean] parameter recupera el valor del parámetro solicitado, y define el resultado como un atributo
de ámbito de página del tipo String o String[].

Ejemplo de utlización de las etiquetas más importantes


<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<HTML>
<HEAD>
<TITLE>Welcome World!!</TITLE>
<html:base/>
</HEAD>
<BODY>
<logic:present name="user">
<H3>Welcome <bean:write name="user" property="username"/>!</H3>
</logic:present>
<logic:notPresent scope="session" name="user">
<H3>Welcome World!</H3>
</logic:notPresent>
<html:errors/>
<UL>
<LI><html:link forward="logon">Sign in</html:link></LI>
<logic:present name="user">
<LI><html:link forward="logoff">Sign out</html:link></LI>
</logic:present>
</UL>
<IMG src='struts-power.gif' alt='Powered by Struts'>
</BODY>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</HTML>

Crear diseños utilizando la infraestructura Struts Tiles


Una de las principales acciones de las etiquetas de la librería tiles son las plantillas.
¿Qué es una plantilla?
La finalidad de una plantilla es tener un aspecto consistente sin tener que codificar este
manualmente en cada una de las páginas.
Una plantilla es una página JSP que utiliza una librería de etiquetas personalizadas JSP para describir
el diseño de una página. La plantilla actúa como una definición del aspecto que tendrán las páginas
de una aplicación, sin especificar el contenido. El contenido se inserta en la página de plantilla en el
momento de la ejecución. Se puede utilizar en múltiples proyectos o páginas la misma plantilla.
Añadir la librería de etiquetas Tiles
Debemos añadir la librería Tiles al descriptor de despliegue antes de poder utilizarla. Localizar el
archivo web.xml y añadir el siguiente texto al elemento taglib:
<taglib>
<taglib-uri>/tags/struts-tiles</taglib-uri>
<taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
</taglib>

Utilizar Tiles
Cuando construimos un Web, podemos considerar que éste está formado por una o varias plantillas
en la que únicamente cada página cambia una porción (normalmente central) del contenido
mostrado respecto a las restantes. La plantilla normalmente contiene un menú, publicidad,
cabeceras, pies, etc.
Tiles permite separar el diseño del contenido, insertando el contenido de forma dinámica.
Las principales características de Tiles se describen a continuación:
 Existe la posibilidad del uso de las mencionadas plantillas.
 Construcción y carga de páginas dinámicas.
 Internacionalización.
 Definición de plantillas.
Principales etiquetas Tiles
Nombre Descripción
add Añade un elemento a la lista
definition Crea una definición de componente Title
get Obtiene el contenido del ámbito de
petición que situó allí una etiqueta put.
getAsString Muestra el valor del atributo de
title/componente/plantilla especificado
para el JSPWriter actual.
importAttribute Importa un atributo de title en el
contexto especificado.
initComponentDefinitions Inicializa un factory de definiciones title
Insert Inserta un componente title
put Sitúa un atributo en un contexto
putList Declara una lista que se pasará como un
atributo
useAttribute Utiliza un valor de atributo dentro de

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
una página

Etiqueta Insert
La etiqueta insert es responsable de insertar contenido en una página. En un title de diseño, la
etiqueta insert prescribe dónde irá el contenido utilizando valores de atributo.
Tabla de atributos de la etiqueta insert
Nombre Descripción
atrribute El nombre de un atributo en el contexto
title/componente actual.
beanName El nombre del bean utilizado como un
valor. El bean se recupera del contexto
especificado.
beanProperty El nombre de la propiedad del bean.
beanScope El ámbito del contexto dónde se puede
utilizar el bean.
component Un string que representa el URI de un
title.
controllerURL El URL del controlador llamado
inmediatamente antes de que se inserte
la página.
controlerClass El tipo de clase del controlador
definition El nombre de la definición a insertar.
Las definiciones se definen en un
archivo centralizado.
flush Bolean. True si el flujo de salida de la
página actual se borra antes de la
inserción del title.
ignore True y el name no existe, regresa sins
escribir nada.
name El nombre de una entidad a insertar.
page String que representa el URI de un title
o plantilla.
role Si el usuario está en el rol especificado,
la etiqueta se tiene en cuenta; de lo
contrario, la etiqueta se salta y el
contenido no se escribe.
template String que representa el URI de un title
o plantilla. Mismo comportamiento que
page y component.
Etiqueta put
La etiqueta put se utiliza para pasar atributos a un componente title. Esta etiqueta se puede utilizar
solamente dentro de las etiquetas insert o definitions.
Tabla de atributos de la etiqueta put
Nombre Descripción
beanName El nombre del bean utilizado para
recuperar el valor.
beanProperty El nombre de propiedad en el bean.
beanScope El ámbito del contexto dónde se puede
utilizar el bean.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ejemplo de uso de plantillas

Plantilla.jsp
En este archivo definimos como debe quedar la plantilla de nuestro sitio web.
Definimos con la etiqueta getAsString donde colocaremos el título de la página:
<tiles:getAsString name="titulo" />
Definimos con la etiqueta insert donde colocaremos el cuerpo:
<tiles:insert attribute="cuerpo"/>

<%@page contentType="text/html"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
<html>
<head><title><tiles:getAsString name="titulo" /></title></head>
<body>
<div align="center">
<center>
<table border="1" cellpadding="2" style="border-collapse:
collapse; border-width: 0" bordercolor="#111111" id="AutoNumber1" width="800">
<tr>
<td width="773" style="border-style: none; border-width: medium" colspan="3">
LOGOS EMPRESA
</td>
</tr>
<tr>
<td width="140" style="border-style: none; border-width: medium">
</td>
<td width="508" style="border-style: none; border-width: medium">
Mensajes
</td>
<td width="117" style="border-style: none; border-width: medium">
login
</td>
</tr>
<tr>
<td width="140" style="border-style: none; border-width: medium">
menu
</td>
<td width="508" style="border-style: none; border-width: medium">
<tiles:insert attribute="cuerpo"/>
</td>
<td width="117" style="border-style: none; border-width: medium">
otros
</td>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</tr>
</table>
</center>
</div>
</body></html>
Index.jsp
Será la página principal de nuestro sitio web, se encargará de utilizar la plantilla previamente
creada.
Introduciremos un valor en las etiquetas titulo e insert.
Titulo: Mostraremos el mensaje de nuestra página principal.
Cuerpo: Indicaremos que el contenido de la página principal se inserte en la etiqueta definida con el
nombre cuerpo.
<%@page contentType="text/html"%>

<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>

<tiles:insert page="/Plantilla.jsp" flush="true" >


<tiles:put name="titulo" value="Página principal de Struts" />
<tiles:put name="cuerpo" value="/paginas/principal.jsp" />
</tiles:insert>
principal.jsp
Contenido que sera insertado por la página index.jsp.
<table border="1" cellpadding="2" style="border-collapse: collapse"
bordercolor="#111111" width="100%" id="AutoNumber2">
<tr>
<td width="100%"><i><b><font size="6" color="#0000FF">Home</font></b></i><p>
Aquí va a ir el cuerpo de la nueva home
</td>
</tr>
</table>
Modificaremos el ejemplo para poder incluir etiquetas de la librería Bean de Struts:
IndexTiles2.jsp: Insertará la etiqueta con la definición de una variable. Posteriormente,
hará uso de la etiqueta para insertar el valor de la variable definida.
Plantilla de nuestro proyecto struts (plantilla2.jsp)
<%@page contentType="text/html"%>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>

<html>
<head><title><tiles:getAsString name="titulo" /></title></head>
<body>

<div align="center">
<center>
<table border="1" cellpadding="2" style="border-collapse:
collapse; border-width: 0" bordercolor="#111111" id="AutoNumber1" width="800">
<tr>
<td width="773" style="border-style: none; border-width: medium" colspan="3">
<a href="http://www.infoservicios.es/">
<img src="imagenes/logoinfostruts.jpg" border="0" width="571" height="77">
</a><a href="http://www.infoempleo.com">
<img src="imagenes/LOGOARRIBA2.GIF" border="0" width="179" height="77">

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</a></td>
</tr>
<tr>
<td width="140" style="border-style: none; border-width: medium">

</td>
<td width="508" style="border-style: none; border-width: medium">
Mensajes
</td>
<td width="117" style="border-style: none; border-width: medium">
login
</td>
</tr>
<tr>
<td width="140" style="border-style: none; border-width: medium">
menu
</td>
<td width="508" style="border-style: none; border-width: medium">
<tiles:insert attribute="cuerpo"/>
</td>
<td width="117" style="border-style: none; border-width: medium">
otros
</td>
</tr>
</table>
</center>
</div>
<br><br><br><b>
<tiles:getAsString name="copyright" /></b>
</body>
</html>
Página que especifica la plantilla a utilizar (IndexTiles2.jsp)

<%@page contentType="text/html"%>
<%@taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>

<bean:define id="copyright" value="copyright 2010 Viva JAVA s.l.,Todos los derechos reservados"
type="String" toScope="request" />

<tiles:insert page="/plantilla2.jsp" flush="true" >


<tiles:put name="titulo" value="Home del Web con Tiles" />
<tiles:put name="cuerpo" value="/tiles/hometile.jsp" />

<tiles:put name="copyright" beanName="copyright" />

</tiles:insert>
Página que rellenará el cuerpo (tiles/hometiles.jsp)
<table border="1" cellpadding="2" style="border-collapse: collapse"
bordercolor="#111111" width="100%" id="AutoNumber2">
<tr>
<td width="100%"><i><b><font size="6" color="#0000FF">Home</font></b></i><p>
Aquí va a ir el cuerpo de la nueva home
</td>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</tr>
</table>

Ver Video: Librería Etiquetas Struts, en la Unidad 14,


en el Módulo 5, en la plataforma elearning

Laboratorio: Librería de etiquetas Logic.


Objetivo
Uso de las librerías de etiquetas de Struts.
Enunciado:
Crear en una clase llamada Libro la lógica de negocio para el mantenimiento de una librería.
Usaremos desde una página jsp los métodos y propiedades del modelo de Struts.
Incorporar en la página jsp etiquetas de la librería Logic para recorrer los libros almacenados en la
librería.

IndexLibros.jsp
<%@ page import="Libros.*" %>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>


<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<%Libro libros[] = new Libro[3];
libros[0] = new Libro();
libros[0].setTitulo("El Zorro");
libros[1] = new Libro();
libros[1].setTitulo("Aprenda Java en 2 horas");
libros[2] = new Libro();
libros[2].setTitulo("Alicia en el pais de la programación");%>

<ol>
<h2>LISTADO DE LIBROS MÁS VENDIDOS:</h2>
<logic:iterate id="misLibros" collection="<%= libros %>">

<b>Titulo =</b> <bean:write name="misLibros" property="titulo"/>


<br/>

</logic:iterate>

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
</ol>
</body>
</html>

Libros.java
package Libros;

import java.util.Vector;

public class Libro


{
private String titulo = "";
private Vector autores = new Vector();
private int paginas = 0;

public Libro()
{
}

public void setTitulo(String titulo)


{
this.titulo = titulo;
}
public String getTitulo()
{
return this.titulo;
}
public void setPaginas(int paginas)
{
this.paginas = paginas;
}

public int getPaginas()


{
return this.paginas;
}

public void addAutor(String autor)


{
this.autores.add(autor);
}
public void borrarAutor(int posicion)
{
this.autores.remove(posicion);
}
public int obtenerNumAutores()
{
return this.autores.size();
}
}

Actividades

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades
que encontrará en la unidad correspondiente de la plataforma eLearning”.

www.learning.es
Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.

Вам также может понравиться