Manual Java Web
Manual Java Web
INTRODUCCIN A JAVA EE
NDICE
1.1 Introduccin ..........................................................................3
1.1.1 Java Card .......................................................................... 3
1.1.2 Java Micro Edition (Java ME) ......................................... 4
1.1.3 Java Standard Edition (Java SE).................................... 4
1.1.4 Java Enterprise Edition (Java EE) .................................. 4
1.2El modelo de aplicacin Java EE........................................5
1.2.1 Componentes Java EE .................................................... 6
1.2.2 Contenedores Java EE .................................................... 7
1.2.3 Servicios Java EE ............................................................. 8
1.3El diseo de aplicaciones Java EE .....................................8
1.4Las especificaciones Java EE...........................................10
1.5El ensamblado y despliegue de aplicaciones Java EE ..13
1.6El Servidor de Aplicaciones Java EE................................15
PARA RECORDAR ....................................................................18
1.1
Introduccin
Debido a la naturaleza del lenguaje Java: portable, seguro, multithread, etc, est siendo
utilizado en multitud de mbitos y tecnologas, desde el chip de una tarjeta de crdito hasta un
servidor de la ms alta gama.
Evidentemente,
estos
distintos
mbitos
entornos,
tienen
unas
caractersticas
Java Card.
Java 2 EE 1.2
4
1.2
El modelo de aplicaciones Java EE define una arquitectura para implementar servicios como
aplicaciones multicapa que aseguren la escalabilidad, accesibilidad y facilidad de gestin
necesarias en un mbito empresarial.
El modelo divide el trabajo a realizar en la implementacin en dos partes:
El desarrollador puede apoyarse en los servicios ofrecidos por la plataforma Java EE en vez de
reinventar la rueda una y otra vez, facilitndole as el concentrarse nicamente en la lgica
especfica de su aplicacin.
La plataforma Java EE utiliza un modelo de programacin distribuido en distintas capas. La
lgica de la aplicacin se divide en distintos componentes dependiendo de su funcionalidad, y
estos son desplegados en las distintas capas dependiendo de a cul pertenecen.
Las distintas capas son:
Capa web (Web Tier): responsable del control de la aplicacin y en ocasiones tambin
de la interaccin con el usuario.
de
Informacin
Empresarial).
Por
ejemplo
ERPs,
BBDD,
Motores
Es muy importante tener en cuenta, que esta divisin es puramente lgica y no fsica. Es decir,
fsicamente cada capa no tendr por qu estar en mquinas independientes, sino que podrn
compartir hardware. Por ejemplo, veremos que lo normal ser que el entorno de desarrollo que
montaremos para resolver las distintas actividades de este curso tendr todas las capas
fsicamente en la misma mquina.
Adicionalmente al tema multicapa, el modelo de aplicacin Java EE define otros tres
conceptos claves para entender la plataforma:
Componentes web: son Java Servlets, JavaServer Pages (JSP) o JavaServer Faces
(JSF). Se despliegan en la capa web.
1.3
Todos los informticos saben, que antes de ponerse a programar hay una fase muy importante
de anlisis y de diseo donde se estudia y define la solucin. Para ello, contamos con el
lenguaje UML (Unified Modeling Language) que define una serie de diagramas y notaciones
para poder plasmar estos anlisis y diseos.
Nota: El lenguaje UML no es objeto de este curso pero se cubre con cierta profundidad en el
curso de Aula Mentor: Programacin en Java Inicial.
Adicionalmente, existe el concepto de Patrones de Diseo, que son un conjunto de soluciones
(o diseos) a los problemas ms comunes en la programacin de aplicaciones, que han
demostrado ser tiles y eficientes en la resolucin de dichos problemas. Su existencia, permite
poder reutilizar y aplicar soluciones existentes, y no estar reinventando la rueda
constantemente.
Pues bien, existe un conjunto importante de estos patrones de diseo muy relacionados con el
desarrollo de aplicaciones Java EE. A lo largo del curso iremos viendo algunos, pero si el
alumno quiere profundizar en este tema tiene el catlogo completo en las Blue Prints de Java
EE:
http://www.oracle.com/technetwork/java/catalog-137601.html
El Modelo (Model): Representa los datos y cualquier lgica de negocio relacionada con
ellos.
Pues bien, los distintos tipos de componentes que hemos introducido en el apartado del
modelo de aplicacin Java EE, encajan perfectamente en este diseo:
Modelo: Enterprise JavaBeans, POJOs (Plain Old Java Objects).
Vista: JavaServer Pages (JSP), JavaServer Faces (JSF).
Controlador: Java Servlets.
Un ejemplo del flujo de una aplicacin Java EE sera algo as:
1. El cliente, por ejemplo un navegador, solicitar una funcionalidad desde el interface
visual (Vista).
2. Dicha peticin entrar a travs de un Java Servlet (Controlador).
3. Dicho Java Servlet, analizar qu se est pidiendo, qu informacin adicional aporta y
decidir que Enterprise JavaBean o POJO (Modelo) cubre dicha peticin.
4. Lo invocar, y tras recibir un resultado, decidir qu JavaServer Page (JSP) muestra
dicho resultado al cliente (Vista).
5. El resultado ser devuelto y mostrado.
Y visualmente:
Evidentemente, las aplicaciones se pueden desarrollar sin tener en cuenta estos patrones de
diseo, pero est demostrado sobradamente en el mercado, el aumento de productividad y
mejora del mantenimiento con su uso.
A lo largo del curso iremos insistiendo en este punto y detallando y practicando tanto este
patrn como otros.
1.4
Las especificaciones Java EE son el conjunto de las definiciones detalladas de los conceptos
que forman parte de la plataforma Java EE: componentes, contenedores y servicios.
10
JavaMail 1.4
Java Authentication Service Provider Interface for Java Authorization Contract for
Containers 1.3
Dado que la plataforma Java EE extiende la Java SE, existen especificaciones Java SE
incluidas en Java EE:
Como ya hemos comentado, la plataforma Java EE es un tema muy extenso que toca gran
cantidad de mbitos y tecnologas. Nosotros en este curso titulado Programacin Web nos
centraremos exclusivamente en aquellas especificaciones relacionadas con la presentacin y
el acceso a Bases de Datos.
Existe documentacin on-line de todas estas especificaciones o APIs que sern de enorme
utilidad a la hora de desarrollar aplicaciones Java EE:
http://download.oracle.com/javaee/6/api/
12
1.5
Una aplicacin Java EE est formada por un empaquetamiento de una o varias unidades
conocidas con el nombre de mdulos. Estos mdulos contienen a su vez:
Uno o varios componentes (Java Servlets, Enterprise JavaBeans (EJB)).
Un descriptor de despliegue que describe el contenido y caractersticas del mdulo
(desde la versin 5.0 estos descriptores son opcionales, ya que el propio cdigo
puede ser auto descriptivo mediante el uso de anotaciones).
Existen distintos tipos de mdulos dependiendo de su contenido y el contenedor donde se
vaya a ejecutar. Los distintos mdulos van empaquetados en un fichero JAR (Java ARchive).
No obstante, la extensin de dicho fichero depender del tipo de mdulo:
Mdulo Web (Web Module): contiene normalmente Java Servlets, JavaServer Pages
(JSP), JavaServer Faces (JSF), contenidos estticos como imgenes, HTMLs, CSSs
La extensin del fichero empaquetado ser WAR (Web ARchive).
Modulo de EJBs (EJB Module): como su nombre indica, contiene Enterprise
JavaBeans (EJB). La extensin del fichero empaquetado es la de por defecto, JAR
(Java ARchive).
Modulo cliente (Application Client Module): contiene el cdigo de la aplicacin cliente.
La extensin del fichero empaquetado es la de por defecto, JAR (Java ARchive).
Modulo
Adaptador
(Resource
Adapter
Module):
13
14
1.6
Hasta aqu, todo han sido especificaciones, definiciones pero para poder ejecutar una
aplicacin Java EE necesitamos un entorno de ejecucin. Dicho entorno de ejecucin se
conoce con el nombre de Servidor de Aplicaciones.
Un Servidor de Aplicaciones por tanto, es un producto de software que implementa todas las
especificaciones Java EE. De manera que al desplegar o instalar una aplicacin Java EE en el
servidor, sabemos seguro que va a encontrarse con todos los contenedores y servicios
definidos por la especificacin y que seguramente utiliza y necesita la aplicacin.
Existe una batera de pruebas estndar que todo proveedor de Servidores de Aplicaciones
debe pasar satisfactoriamente para poder decir que es Java EE. Es lo que se conoce con el
nombre de JCK (java Compatibility Kit o Kit de Compatibilidad Java).
Gracias a la existencia del estndar Java EE, podemos tener la tranquilidad de que nuestra
aplicacin debe funcionar perfectamente en el Servidor de Aplicaciones de cualquier
proveedor, asegurndonos as que no debemos de trabajar con ninguno en concreto.
Existen multitud de Servidores de Aplicaciones en el mercado. Podramos categorizarlos de la
siguiente forma:
Gratuitos o de pago.
Certificados Java EE o no.
A continuacin comentamos algunos. No estn todos los que son, ni son todos los que estn,
pero si los ms usados y conocidos:
Apache Tomcat: Es gratuito de cdigo abierto. No cumple con el 100% de las
especificaciones Java EE por lo que no se puede decir que sea un Servidor de
Aplicaciones Java EE. Pero si que cubre algunas de las especificaciones relacionadas
con la programacin web que estudiamos en este curso: Java Servlet 3.0, JavaServer
Pages 2.2, Java Database Connectivity 4.0 y Java Naming and Directory Interface 1.2
Este es el Servidor de Aplicaciones que usaremos en este curso. En los Materiales de
Apoyo de la Mesa del Alumno, encontraris las instrucciones de descarga, instalacin
y configuracin del servidor.
URL: http://tomcat.apache.org
15
Jetty: Es gratuito y de cdigo abierto. Al igual que pasara con Apache Tomcat,
tampoco implementa el 100% de las especificaciones Java EE. Una vez ms, se
centra exclusivamente en algunas especificaciones web.
URL: http://jetty.codehaus.org/jetty/
WebSphere Application Server: Es de pago de la empresa IBM. Se trata de un Servidor
de Aplicaciones Java EE completo.
URL: http://www-01.ibm.com/software/webservers/appserv/was/
URL: http://geronimo.apache.org
16
URL: http://glassfish.java.net/
URL: http://www.jboss.org/jbossas
17
PARA RECORDAR
En esta unidad hemos visto la diferencia entre las distintas versiones de Java: Java
Card, Java Micro Edition, Java Standar Edition y Java Enterprise Edition (Java
EE).
Las aplicaciones Java EE, estn distribuidas en distintas capas para una mejor
organizacin funcional: capa cliente (para interactuar con el usuario), capa web
(para llevar el control de la aplicacin y a veces interactuar con el usuario), capa de
negocio (contiene la lgica del negocio como tal) y la capa de datos (contiene la
informacin de negocio).
A su vez la plataforma Java EE, para poder ejecutar las aplicaciones Java EE
multicapa, est formada por:
Componentes: Unidades de software que forman o componen la aplicacin
Contenedores: Entorno de ejecucin donde se ejecutan los componentes.
Servicios: Funcionalidades estndar que todo contenedor debe proveer a los
componentes.
Para poder disear aplicaciones Java EE, ya existen distintos patrones de diseo
muy extendidos que posibilitan la reutilizacin de los componentes y un mejor
mantenimiento de los mismos, como es el patrn Modelo-Vista-Controlador
(MVC).
Para que una aplicacin Java EE, pueda ejecutarse en un servidor Java EE, estos
deben de cumplir las especificaciones determinadas en una versin dada o al
menos aquellas necesarias para el tipo de aplicacin que se desea implementar.
Las aplicaciones Java EE (fichero EAR) estn formadas por al menos un mdulo de
los siguientes tipos: Mdulo Web (fichero WAR), Modulo de EJBs (fichero JAR),
Modulo cliente (fichero JAR), Modulo Adaptador (fichero RAR).
18
Gratuitos o de pago.
19
20
Unidad de Aprendizaje 2
EL ENTORNO DE DESARROLLO
NDICE
2.1
Introduccin ................................................................... 23
2.2
PARA RECORDAR.................................................................... 40
2.1
Introduccin
URL: http://www.oracle.com/technetwork/java/javaee/downloads/index.html
URL: http://www.eclipse.org/
23
URL: http://www.ibm.com/software/awdtools/developer/application/
URL: http://netbeans.org/
URL: http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.html
2.2
A continuacin, describiremos los pasos para descargar, instalar y configurar las herramientas
seleccionadas
en
este
curso
anteriormente
mencionadas
para
poder
realizar
24
25
Para instalarlo, ejecutar el fichero descargado (en nuestro ejemplo, jre-7u1-windowsx64.exe), mediante doble click del ratn.
26
Pulsar el botn Install > para comenzar la instalacin. Durante dicho proceso, aparecer
una barra mostrando el progreso de la instalacin.
Nota: La ubicacin por defecto donde se instalar el JRE es C:\Program Files\Java\jre7; si
deseamos instalarlo en una ubicacin distinta, marcar la casilla Change destination folder
antes de pulsar el botn Install >.
27
29
Aparecer una pgina con el mejor servidor para descargar el fichero que hemos solicitado
dependiendo de nuestra conexin y localizacin. Simplemente pulsar sobre la flecha verde y
guardar el fichero en un directorio temporal:
30
No obstante, a excepcin del cambio de nmero y por tanto de nomenclatura, todos los
pasos de descarga, instalacin y configuracin aqu descritos deberan seguir siendo vlidos.
El alumno puede elegir por tanto el instalar el Update 1 o elegir otro Update posterior.
Descomprimir el fichero que hemos descargado (en nuestro ejemplo, eclipse-jee-indigo-SR1win32-x86_64.zip) en el disco duro donde queramos tener Eclipse. Por ejemplo:
D:\eclipse-jee-indigo-SR1-win32-x86_64
Arrancar Eclipse ejecutando:
D:\eclipse-jee-indigo-SR1-win32-x86_64\eclipse.exe
Nos preguntar por la ubicacin del workspace (o rea de trabajo) donde Eclipse va a ir
guardando todos los proyectos y ficheros que vayamos desarrollando:
32
33
Descargar y descomprimir el fichero (en nuestro ejemplo, apache-tomcat-7.0.22-windowsx64.zip) en el disco duro donde queramos tener Eclipse. Por ejemplo:
D:\apache-tomcat-7.0.22
34
35
Pulsaremos el botn derecho del ratn sobre la zona en blanco de esta vista, y elegiremos la
opcin New -> Server del men:
36
37
38
Seleccionaremos la opcin Start y veremos como aparecer una nueva vista denominada
Console donde ir apareciendo el log del servidor. En este caso, deberamos ver cmo va
saliendo toda la informacin del arranque. Algo parecido a esto:
Volviendo a la vista Servers, veremos como el estado del servidor ahora ha cambiado
poniendo [Started, Synchronized].
Podemos parar el servidor nuevamente desde el mismo men de opciones desde donde lo
arrancamos en el paso anterior y una vez lo haya hecho, cerrar Eclipse.
Con esto damos por finalizada la instalacin y configuracin del entorno de desarrollo
necesario para llevar a cabo este curso.
39
PARA RECORDAR
40
Unidad de Aprendizaje 3
PROTOCOLO HTTP Y
LENGUAJE HTML
NDICE
3.1
Introduccin ................................................................... 43
3.2
3.3
El lenguaje HTML........................................................... 54
3.3.1 La etiqueta HTML ...........................................................55
3.3.2 La pgina HTML..............................................................56
3.3.3 El formulario HTML.........................................................57
3.3.3.1 Camposdetexto ......................................................58
3.3.3.2 reasdetexto ..........................................................59
3.3.3.3 Checkboxes...............................................................60
3.3.3.4 Radiobuttons............................................................61
3.3.3.5 ListasyCombos ........................................................62
3.3.3.6 Botones ....................................................................63
3.3.3.7 Camposocultos ........................................................64
3.4
PARA RECORDAR.................................................................... 67
3.1
Introduccin
Cono podemos observar, el TCP/IP implementa los niveles tericos en cuatro, a travs de
distintos protocolos como IP en el nivel que llama Internet, TCP y UDP entre otros en el nivel
que llama Transporte, y HTTP, FTP, Telnet, etc en el nivel que llama Aplicacin. Es en este
ltimo nivel donde se encuentra el protocolo HTTP que realmente nos interesa para programar
aplicaciones Java EE aunque este, sin el resto de los niveles sera intil. De ah que se hayan
mencionado en esta introduccin.
Por otro lado, tenamos el lenguaje de etiquetado HTML, la otra piedra angular sobre la que se
sustenta Internet. El HTML es el lenguaje mediante el cual definimos los contenidos que fluyen
por Internet, conocidas como pginas HTML o pginas Web.
Y quizs sin saberlo, todos los das estamos usando ambos dos fundamentos. Los
navegadores web (IExplorer, Firefox, Chrome, Opera) no son mas que aplicaciones que
implementan el protocolo HTTP a travs del cual se reciben bajo peticin pginas HTML.
Por qu es tan importante tener claro los conceptos del HTTP y HTML entonces? Porque las
aplicaciones Java EE que vamos a aprender a desarrollar, son las que estn al otro lado
sirviendo las peticiones de los navegadores web. Por tanto, van a tener que entender el
protocolo HTTP y van a tener que saber contestar con pginas HTML que muestran la
informacin solicitada.
Nota: como decamos al inicio de esta introduccin, esta es una visin muy simplista pero que
proporciona una idea clara. Es simplista en el sentido de que no solo se utiliza el protocolo
HTTP (aunque si en la mayora de los casos) ni siempre se utiliza HTML como medio para
mostrar la informacin (aunque nuevamente si en la mayora de los casos). Otras opciones a
modo de ejemplo, mucho menos utilizadas, seran protocolos como FTP o Telnet, y lenguajes
de etiquetado como WML o cHTML.
3.2
El protocolo HTTP
Como hemos dicho ya, el protocolo HTTP es el protocolo fundamental desde el punto de vista
del desarrollo de aplicaciones Java EE. Es el encargado de la transferencia de los recursos
que componen la red.
Es un protocolo que sigue un esquema de peticin respuesta (request response) entre un
cliente (habitualmente un navegador) y un servidor (habitualmente un servidor de aplicaciones
Java EE como ya vimos en las unidades anteriores) donde el cliente solicita un recurso y el
servidor se lo devuelve.
Actualmente se encuentra en su versin 1.1, y es un estndar definido por el IETF (RFC 2616):
http://www.ietf.org/rfc/rfc2616.txt
44
Y con el nombre del recurso ocurre igual. Est establecido que por defecto si no se
especifica el nombre del recurso, las aplicaciones prueben con unos nombres por defecto
que suelen ser:
index.html
index.htm
index.jsp
etc
Por tanto, una URL equivalente a la analizada y con mismo resultado sera:
http://www.google.es
Los servidores en Internet se identifican mediante direcciones IP que consisten en cuatro
grupos de nmeros desde el 0 al 255 separados por puntos, por ejemplo:
74.125.39.103
Todo servidor en Internet tiene asignada una direccin IP nica. Si no fuese as, sera
inaccesible porque al hacer una peticin, el sistema de comunicaciones TCP/IP no sabra
con cul conectar. Como el uso de estas direcciones es algo complejo para los usuarios
(difciles de recordar, fcil de cometer un error), existen unos servidores especiales
denominados DNS (Domain Name Server o Servidores de Nombres de Dominio) que se
encargan de traducir nombres legibles y fciles de recordar por los usuarios a direcciones IP.
Esta traduccin mediante la conexin a los servidores DNS la hace el sistema de
comunicaciones TCP/IP, que comentamos en la introduccin, automticamente sin la
intervencin del usuario.
Por ejemplo, en el momento de la redaccin de este manual, la direccin IP de
www.google.es era la del ejemplo: 74.125.39.103, es decir, que en el navegador deberamos
ver la misma pgina si escribiramos:
http://74.125.39.103
o si escribiramos:
http://ww.google.es
3.2.2 Conversaciones HTTP
Como ya comentamos al inicio de este captulo, HTTP es un protocolo que sigue un
esquema de peticin respuesta (request response) entre un cliente (habitualmente un
navegador) y un donde el cliente solicita un recurso y el servidor se lo devuelve.
Una peticin HTTP se compone a grandes rasgos de:
Mtodo HTTP: se trata de la accin a realizar. Algunos ejemplos como veremos mas
adelante son GET y POST.
Recurso sobre el que actuar: es decir, una URL.
46
POST es el mtodo que habitualmente se utiliza para enviar parmetros, porque van en el
cuerpo de la peticin en vez de aadidos a la URL del recurso solicitado.
Veamos el mismo ejemplo que antes para identificar las diferencias. En este caso la peticin
sera:
POST /EjemploWeb/Sumador HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Referer: http://127.0.0.1/EjemploWeb/index.html
Accept-Language: en-us,es;q=0.5
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;
SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: 127.0.0.1:8080
Content-Length: 19
Connection: Keep-Alive
Cache-Control: no-cache
param1=45¶m2=21
Nuevamente identificamos que se trata de una peticin HTTP porque la primera lnea
comienza con un mtodo HTTP. Y vemos, que a diferencia de lo que ocurra con el mtodo
GET, en esta ocasin la URL no incluye ningn parmetro sino que el mensaje tiene un
cuerpo con dichos parmetros.
Hay alguna diferencia en alguna cabecera ms, pero tampoco entraremos en tanto detalle.
La respuesta sera:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=304CE17CCEB55869A606CE06271F915B;
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 314
Date: Sun, 08 Jun 2008 09:27:24 GMT
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1">
<TITLE>Calculadora</TITLE>
</HEAD>
<BODY>
El resultado de la suma de 45 y 21 es: 66
</BODY>
</HTML>
Como vemos, es igual que la del ejemplo anterior, ya que lo que nos devuelve el servidor si
le pedimos lo mismo (aunque sea por dos mtodos distintos) siempre ser lo mismo.
Los parmetros que se envan en una peticin, pueden ser cualquier carcter alfanumrico
ASCII, incluyendo los caracteres: . (punto), - (guion), * (asterisco) y _ (subrayado). Cualquier
otro tipo de carcter ha de ir codificado:
El espacio en blanco con el carcter + (suma).
Cualquier otro carcter con un valor hexadecimal de la forma %xx. Por ejemplo, la
(ee), con %F1. En Internet estn las tablas de conversin y el propio lenguaje Java
50
51
52
mquina y lo renviaremos al 8080 del servidor de aplicaciones (que en este ejemplo, tambin
est en nuestra mquina):
en la siguiente
unidad.
3.3
El lenguaje HTML
El HTML (HiperText Markup Languaje) es el lenguaje utilizado para crear documentos web (o lo
que comnmente se denominan pginas web). Bsicamente se trata de un lenguaje de
etiquetado, que define la estructura y el contenido de un documento a ser compartido y
accedido en Internet a travs de un navegador web.
Junto con el protocolo HTTP son la base sobre la que se construy la red de redes conocida
como Internet.
Este lenguaje est estandarizado bajo la supervisin del W3C. En el momento de la redaccin
de este manual, la ltima versin del lenguaje HTML es la 4.01:
http://www.w3.org/TR/html4/
aunque la siguiente versin, 5.0, est en proceso de definicin:
http://www.w3.org/TR/html5/
No obstante, el lenguaje HTML requerira un manual dedicado para cubrir todas sus
caractersticas y posibilidades. En nuestro caso, al igual que hemos hecho con el protocolo
HTTP, solo haremos un breve recorrido introductorio para conocer lo imprescindible que nos
permita desarrollar aplicaciones Java EE.
54
55
Miprimerejercicio
</BODY>
</HTML>
Este cdigo HTML debera ir salvado en un fichero de extensin *.html y al abrirlo en un
navegador, veramos algo as:
La primera lnea es un tanto especial. Se trata de una etiqueta de descripcin tcnica del
fichero HTML donde especifica la versin de HTML utilizada, entre otras cosas.
56
57
Este formulario va a enviar a un Java Servlet del servidor mediante el mtodo HTTP POST
toda la informacin que contenga. De momento, tal cual est en el ejemplo, no contiene
ninguna informacin.
Un formulario puede contener distintos elementos para recoger informacin del usuario:
Campos de texto.
reas de texto.
Checkboxes.
Radiobuttons.
Listas y combos.
Botones.
Campos ocultos.
Veamos uno por uno.
3.3.3.1 Camposdetexto
Un campo de texto se define mediante la etiqueta INPUT y su atributo type con el valor
text.
Admite otros atributos como son:
Name: el nombre del campo y por tanto, nombre del parmetro que viajar al servidor.
Value: valor que debe aparecer por defecto si as se desea.
Size: tamao del campo en la pantalla desde un punto de vista visual.
Maxlength: nmero mximo de caracteres que se pueden introducir en este campo.
Disabled: no tiene un valor, sino que su sola presencia significa que el campo est
deshabilitado.
Esta etiqueta no requiere su homnima de final.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Introduzcasunombre:
<INPUTtype=textname=nombremaxlength=20>
</FORM>
El navegador mostrara algo as:
58
Existe un caso particular de campo de texto, que es el utilizado para introducir informacin
secreta (como por ejemplo una contrasea) donde no se quiere que se pueda leer la
informacin tecleada.
Se define igual que el campo de texto con la diferencia de que el atributo type debe tener
el valor password.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Introduzcasucontrasea:
<INPUTtype=passwordname=contrasenamaxlength=20>
</FORM>
El navegador mostrara algo as:
3.3.3.2
reasdetexto
Esta etiqueta si requiere su homnima de final. Y el contenido que queramos que aparezca
por defecto en ella si as lo deseamos, debe ir entre ambas etiquetas.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Introduzcasuscomentarios:<BR>
<TEXTAREAname=comentarioscols=10rows=20>
</TEXTAREA>
</FORM>
El navegador mostrara algo as:
3.3.3.3
Checkboxes
Una checkbox se define mediante la etiqueta INPUT y su atributo type con el valor
checkbox.
Admite otros atributos como son:
Name: el nombre del campo y por tanto, nombre del parmetro que viajar al servidor.
Value: el valor del campo en caso de estar seleccionado.
Checked: no tiene un valor, sino que su sola presencia significa que la checkbox est
seleccionada por defecto.
Disabled: no tiene un valor, sino que su sola presencia significa que el campo est
deshabilitado.
Esta etiqueta no requiere su homnima de final.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Seleccionesusdeportesfavoritos:
<BR>
Ftbol:<INPUTtype="checkbox"name="futbol"value="true"
checked><BR>
60
3.3.3.4
Radiobuttons
Un radiobutton se define mediante la etiqueta INPUT y su atributo type con el valor radio.
Admite otros atributos como son:
Name: el nombre del campo y por tanto, nombre del parmetro que viajar al servidor.
Si varios radiobuttons comparten el mismo nombre, entonces forman un grupo donde
solo uno de ellos puede estar seleccionado.
Value: el valor del campo en caso de estar seleccionado.
Checked: no tiene un valor, sino que su sola presencia significa que el radiobutton est
seleccionada por defecto.
Disabled: no tiene un valor, sino que su sola presencia significa que el campo est
deshabilitado.
Esta etiqueta no requiere su homnima de final.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Seleccionesusexo:<BR>
<INPUTtype="radio"name="sexo"value="tipo1"checked>Hombre
<BR>
<INPUTtype="radio"name="sexo"value="tipo2">Mujer<BR>
</FORM>
El navegador mostrara algo as:
61
3.3.3.5
ListasyCombos
Tanto las listas como los combos se definen mediante la etiqueta SELECT.
Admite los siguientes atributos:
Name: el nombre del campo y por tanto, nombre del parmetro que viajar al servidor.
Size: especifica el nmero de valores visible. Si solo es visible un valor, se mostrar
como un Combo. Si son visibles dos o ms, se mostrar como una lista.
Multiple: no tiene un valor, sino que su sola presencia significa que se pueden
seleccionar ms de un elemento a la vez.
Disabled: no tiene un valor, sino que su sola presencia significa que el campo est
deshabilitado.
Esta etiqueta si requiere su homnima de final. Y las distintas opciones que vayan a formar
parte de la lista debern ir definidas entre ambas mediante la etiqueta OPTION.
La etiqueta OPTION admite los siguientes atributos:
Value: el valor del campo en caso de estar seleccionado.
Selected: no tiene un valor, sino que su sola presencia significa que esta opcin est
seleccionada por defecto.
Esta etiqueta si requiere su homnima de final. Y el contenido que queramos que aparezca
como opcin debe ir entre ambas etiquetas.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
Seleccioneelpostre:<BR>
<SELECTname="postre"size="3">
<OPTIONvalue="op1">Fruta</OPTION>
<OPTIONvalue="op2"selected>Helado</OPTION>
<OPTIONvalue="op3">Cuajada</OPTION>
<OPTIONvalue="op4">Tarta</OPTION>
</SELECT>
</FORM>
62
3.3.3.6
Botones
Un botn se define mediante la etiqueta INPUT. Y dependiendo del valor que tenga su
atributo type ser de un tipo u otro:
Button: se trata de un botn genrico que por s solo no hace nada. Hay que
acompaarlo de JavaScript, por ejemplo, para que realice alguna operativa.
Submit: se trata de un botn que al ser pulsado enva toda la informacin recogida en
el formulario al recurso del servidor identificado en el atributo action del formulario
mediante el mtodo HTTP especificado en el atributo method del formulario.
Reset: se trata de un botn que al ser pulsado borra toda la informacin recogida en el
formulario.
Admite otros atributos como son:
Name: el nombre del botn, que puede ser til cuando se programa con JavaScript en
la pgina HTML.
Value: el texto que aparece escrito en el botn.
Disabled: no tiene un valor, sino que su sola presencia significa que el botn est
deshabilitado.
Esta etiqueta no requiere su homnima de final.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
<INPUTtype="submit"value="Enviar">
<INPUTtype="reset"value="Borrar">
</FORM>
El navegador mostrara algo as:
63
3.3.3.7
Camposocultos
Existen ocasiones, en las que nos interesar que como parte del formulario se enve
informacin no visible para el usuario pero necesaria para la lgica de nuestra aplicacin.
Dichos campos se definen mediante la etiqueta INPUT y su atributo type con el valor
hidden.
Admite otros atributos como son:
Name: el nombre del campo y por tanto, nombre del parmetro que viajar al servidor.
Value: el valor del campo, no modificable por el usuario.
Esta etiqueta no requiere su homnima de final.
Ejemplo:
<FORMmethod=POSTaction=/EjemploWeb/EjemploServlet>
<INPUTtype=hiddenname=usuariovalue=1234>
</FORM>
Evidentemente, en el navegador no se vera nada.
Pues bien, esto es todo lo que hay que conocer de HTML para poder interactuar entre el
usuario y la aplicacin Java EE mediante un navegador web. Cualquier otra etiqueta HTML
ya sera para dar formato a la pgina: tablas, cabeceras, imgenes, enlaces, frames, etc
3.4
Ensamblado y despliegue
65
66
PARA RECORDAR
Se han estudiado los mtodos GET y POST para las solicitudes de recursos
estticos y dinmicos a un servidor de aplicaciones, su formato tanto en las
peticiones como en las respuestas y la utilizacin de sniffers para poder depurar
las solicitudes.
HTML es el lenguaje mediante el cual definimos los contenidos que fluyen por
Internet, conocidas como pginas HTML o pginas Web. Bsicamente se trata de
un lenguaje de etiquetado, que define la estructura y el contenido de un documento
a ser compartido y accedido en Internet a travs de un navegador web.
Una etiqueta es un elemento que define qu o como se debe presentar la
informacin que viene a tras la etiqueta, dentro de una pgina web.
Una pgina HTML, es un fichero de texto con extensin *.htm o *.html que
contiene una informacin formateada mediante el lenguaje HTML. Est formada
normalmente por una cabecera <HEAD> y un cuerpo <BODY>.
68
Unidad de Aprendizaje 4
JAVA SERVLETS
NDICE
4.1
Introduccin ................................................................... 71
4.2
4.3
RECORDAR............................................................................. 103
4.1
Introduccin
Ya vimos en la primera unidad del curso, que los Java Servlets eran un tipo de componente
Java EE que se empaquetaba en un mdulo web (WAR) y se desplegaba y ejecutaba en el
contenedor web de un Servidor de Aplicaciones Java EE.
Adicionalmente, dentro del patrn de diseo MVC ocupaban el espacio del Controlador, como
receptor/validador de peticiones, seleccionador de la lgica a ejecutar, y seleccionador de la
vista a presentar como resultado.
Repetimos, esto es un mal diseo y una mala prctica de programacin. Pero consideramos
que es imprescindible ir aprendiendo poco a poco. Por tanto, este diseo es temporal
mientras avanzamos en las sucesivas unidades del curso.
71
Por ltimo, desde un punto de vista del lenguaje de programacin Java, un Java Servlet no es
ms que una clase Java que implementa una determinada interface definida en las
especificaciones.
4.2
Antes de entrar a estudiar en profundidad los Java Servlets, vamos a guiar los pasos para
desarrollar nuestro primer Java Servlet con Eclipse IDE for Java EE Developers y desplegarlo
en Apache Tomcat. Es requisito indispensable, haber seguido los pasos de instalacin y
configuracin de ambas dos herramientas detallados en la unidad 2 de este curso.
Estos mismos pasos nos servirn para los sucesivos ejemplos y actividades del resto del
curso.
Arrancamos Eclipse IDE for Java EE Developers y mediante el las opciones de men File ->
New -> Dynamic Web Project:
Creamos la estructura de desarrollo de un mdulo web (WAR). Como nombre del proyecto,
pondremos HolaMundoWeb, y nos aseguraremos que seleccionamos Apache Tomcat v7.0
72
En la ltima ventana del asistente, antes de pulsar el botn Finish, nos aseguramos de
marcar la opcin Generate web.xml deployment descriptor:
73
74
75
76
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassHolaMundoServletextendsHttpServlet
{
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponse
resp)throwsServletException,IOException
{
resp.setContentType("text/html;charset=UTF8");
PrintWriterout=resp.getWriter();
77
out.println("<!DOCTYPEHTMLPUBLIC\"//W3C//DTDHTML4.01
Transitional//EN\">");
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>HolaMundo!</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("HolaMundo!");
out.println("</BODY>");
out.println("</HTML>");
}
}
No nos preocupemos en este momento por no entender el cdigo. De momento, simplemente
queremos mostrar los pasos para el desarrollo y despliegue de un Java Servlet. En los
sucesivos apartados iremos entendiendo el por qu de cada lnea.
A continuacin, editaremos el descriptor de despliegue del mdulo web, el fichero web.xml de
/WebContent/WEB-INF y aadiremos este cdigo XML salvando al final el fichero:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>HolaMundoServlet</servletname>
<servletclass>es.aulamentor.HolaMundoServlet</servletclass>
</servlet>
<servletmapping>
<servletname>HolaMundoServlet</servletname>
<urlpattern>/HolaMundoServlet</urlpattern>
</servletmapping>
</webapp>
Ya solo queda, probar la aplicacin. Para ello, pulsamos el botn derecho sobre la clase del
Java Servlet -> Run As -> Run on Server:
78
79
En la vista de Console veremos las trazas que va dejando el Servidor de Aplicaciones Java
EE al arrancar, cmo despliega la aplicacin y automticamente abre un navegador interno de
Eclipse IDE con la URL: http://localhost:8080/HolaMundoWeb/HolaMundoServlet donde se ve
el resultado de nuestro primer Java Servlet:
80
Perfectamente podramos utilizar otro navegador web (tipo Mozilla Firefox o Internet Explorer)
y escribir la misma URL. El comportamiento debera ser el mismo.
Para abrir el navegador interno de Eclipse IDE a mano, utilizar el botn de la barra de
herramientas:
Otra opcin tambin vlida habra sido utilizar el asistente de Java Servlets directamente en
vez del asistente de una clase Java convencional, pero preferamos que se viera un ejemplo a
mano. Esta opcin, habra sido con las opciones de men New -> Servlet:
81
Este asistente, aade una anotacin especial sobre la clase Java en el cdigo fuente de
manera que no es necesario aadir nada al descriptor de despliegue. Como ya comentamos
en la primera unidad, esta era una novedad de la ltima versin de la especificacin Java EE.
En este curso, comentaremos ambas dos opciones.
Ya solo nos queda desinstalar la aplicacin mediante la opcin Add and Remove:
82
83
4.3
Java Servlets
Todas las clases Java relacionadas con los Java Servlets, estn en los paquetes:
Los
javax.servet
javax.servlet.http
Java
Servlets
fueron
concebidos
para
ser
independientes
del
protocolo
de
comunicaciones. Pero la realidad ha sido, que el 99% de su uso est relacionado con el
protocolo HTTP (redes Internet e Intranets). De ah, que existan clases en el API que nos
ayudan a gestionar las peculiaridades de dicho protocolo en el segundo paquete mencionado:
javax.servlet.http
4.3.1 El ciclo de vida de un Java Servlet
Un Java Servlet tiene definido un ciclo de vida, forzado por la interface javax.servlet.Servlet,
por tanto, siempre que queramos implementar un Java Servlet, nuestra clase deber
84
85
Por ejemplo, si recordamos de la unidad anterior donde hablbamos del protocolo HTTP,
comentbamos que existan distintos mtodos utilizables en la peticin: GET, POST, PUT,
etc
Pues esta clase, implementa un mtodo Java por cada mtodo HTTP existente, de forma,
qu l ya se encarga de recibir la peticin HTTP, examinarla, e invocar el mtodo Java
correspondiente al mtodo HTTP utilizado, as como darnos acceso a un par de objetos que
representan tanto la peticin como la respuesta HTTP. Los ms habituales que utilizaremos
nosotros son:
Dichos mtodos normalmente los sobrescribiremos en nuestro Java Servlet para incluir
nuestra lgica particular.
Veamos un ejemplo de un Java Servlet que simplemente muestra por la consola del Servidor
de Aplicaciones Java EE trazas del ciclo de vida:
packagees.aulamentor;
importjava.io.IOException;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassCicloDeVidaServletextendsHttpServlet
{
publicCicloDeVidaServlet()
{
super();
System.out.println("CicloDeVidaServlet()");
}
publicvoidinit(ServletConfigconfig)throwsServletException
{
System.out.println("init()");
}
publicvoiddestroy()
{
System.out.println("destroy()");
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
System.out.println("doGet()");
}
}
El editor de despliegue tendra algo as:
86
Como podemos ver, en la consola salen en negro las trazas que dejamos desde nuestro
cdigo: primero el constructor, seguido del init(), seguido de tres doGet() porque ese fue el
87
nmero de veces que invocamos seguidas el Java Servlet, y por ltimo, al apagar el Servidor
de Aplicaciones Java EE el destroy().
En el navegador, evidentemente no se ve nada, puesto que no devolvimos ningn resultado
en el cdigo del Java Servlet.
recibe
dos
parmetros:
javax.servlet.http.HttpServletRequest
javax.servlet.http.HttpServletResponse.
javax.servlet.http.HttpServletRequest, es un interfaz que define cmo interactuar con la
informacin que viene en una peticin HTTP, como por ejemplo, las cabeceras HTTP de la
peticin, los parmetros de la peticin, etc
Algunos mtodos son:
java.util.Enumeration<java.lang.String> getParameterNames(): devuelve una coleccin
con los nombres de todos los parmetros enviados en la peticin.
java.lang.String getParameter(java.lang.String name): devuelve el valor de un
parmetro concreto enviado en la peticin.
java.lang.String[] getParameterValues(java.lang.String name): devuelve todos los
valores de un parmetro concreto enviado en la peticin (imaginemos un conjunto de
checkboxes con el mismo nombre de un formulario).
java.util.Enumeration<java.lang.String> getAttributeNames(): devuelve una coleccin
con los nombres de todos los atributos de la peticin.
java.lang.Object getAttribute(java.lang.String name): devuelve el valor de un atributo
concreto de la peticin.
java.util.Enumeration<java.lang.String> getHeaderNames(): devuelve una coleccin
con los nombres de todas las cabeceras HTTP enviadas en la peticin.
java.lang.String getHeader(java.lang.String name): devuelve el valor de una cabecera
HTTP concreta de la peticin.
java.lang.String getContextPath(): devuelve la porcin de URL de la peticin que
corresponde al ContextPath. El ContextPath es el identificador que utiliza el Servidor
de aplicaciones Java EE para diferenciar una aplicacin u otra. Siempre va en la URL
por delante del recurso pedido como tal.
Existen muchos mtodos ms, algunos muy importantes para el manejo de la Sesin HTTP
y de las Cookies (los veremos en la siguiente unidad), para redireccionar la peticin a otro
java Servlet o JavaServer Page (tambin los veremos en una unidad posterior) y otros
88
importjava.io.IOException;
importjava.util.Enumeration;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassRequestServletextendsHttpServlet
{
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
System.out.println("ContextPath:"+request.getContextPath());
System.out.println("LocalAddr:"+request.getLocalAddr());
System.out.println("LocalName:"+request.getLocalName());
System.out.println("LocalPort:"+request.getLocalPort());
System.out.println("Method:"+request.getMethod());
System.out.println("Protocol:"+request.getProtocol());
System.out.println("QueryString:"+request.getQueryString());
System.out.println("RemoteAddr:"+request.getRemoteAddr());
System.out.println("RemoteHost:"+request.getRemoteHost());
System.out.println("RemotePort:"+request.getRemotePort());
System.out.println();
Enumeration<String>headers=request.getHeaderNames();
while(headers.hasMoreElements())
{
Stringheader=headers.nextElement();
System.out.println(header+":"+request.getHeader(header));
}
System.out.println();
Enumeration<String>parameters=request.getParameterNames();
while(parameters.hasMoreElements())
{
Stringparameter=parameters.nextElement();
System.out.println(parameter+":"+
request.getParameter(parameter));
}
}
}
Y el descriptor de despliegue:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>RequestServlet</servletname>
<servletclass>es.aulamentor.RequestServlet</servletclass>
</servlet>
<servletmapping>
89
<servletname>RequestServlet</servletname>
<urlpattern>/RequestServlet</urlpattern>
</servletmapping>
</webapp>
Si en el navegador utilizamos la siguiente URL para invocar el Java Servlet:
http://localhost:8080/EjemplosWeb/RequestServlet?param1=valor1¶m2=valor2
Nota: Fijaros, que hemos aadido dos parmetros en la URL.
En la consola del Servidor de Aplicaciones Java EE deberamos ver algo como esto (en cada
caso depender un poco del entorno utilizado):
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.IOException;
importjava.io.OutputStream;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassResponseServletextendsHttpServlet
{
privatebyte[]buffer=newbyte[0];
publicvoidinit(ServletConfigconfig)throwsServletException
{
try
{
Filefile=newFile("C:\\images\\duke.gif");
FileInputStreamin=newFileInputStream(file);
buffer=newbyte[(int)file.length()];
in.read(buffer);
in.close();
}
catch(FileNotFoundExceptionex)
91
{
ex.printStackTrace();
}
catch(IOExceptionex)
{
ex.printStackTrace();
}
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
response.setContentType("image/gif");
response.setContentLength(buffer.length);
response.getOutputStream().write(buffer);
response.setStatus(200);
}
}
Y el descriptor de despliegue:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>ResponseServlet</servletname>
<servletclass>es.aulamentor. ResponseServlet</servletclass>
</servlet>
<servletmapping>
<servletname>ResponseServlet</servletname>
<urlpattern>/ResponseServlet</urlpattern>
</servletmapping>
</webapp>
Si en el navegador utilizamos la siguiente URL para invocar el Java Servlet:
http://localhost:8080/EjemplosWeb/ResponseServlet
En el navegador deberamos ver la imagen que hemos utilizado en el ejemplo
<TD>Primernmero:</TD>
<TD><INPUTname="param1"></TD>
</TR>
<TR>
<TD>Segundonmero:</TD>
<TD><INPUTname="param2"></TD>
</TR>
<TR>
<TD><INPUTtype="submit"value="Sumar"></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
Y el siguiente Java Servlet:
packagees.aulamentor;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassSumadorServletextendsHttpServlet
{
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
procesarPeticion(request,response);
}
93
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
procesarPeticion(request,response);
}
privatevoidprocesarPeticion(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
response.setContentType("text/html;charset=UTF8");
try
{
intparam1=Integer.parseInt(request.getParameter("param1"));
intparam2=Integer.parseInt(request.getParameter("param2"));
intresult=param1+param2;
response.setStatus(200);
PrintWriterout=response.getWriter();
out.println("");
out.println("<!DOCTYPEHTMLPUBLIC\"//W3C//DTDHTML4.01
Transitional//EN\">");
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Calculadora</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("Elresultadodelasumaes:"+result);
out.println("<BR><BR>");
out.println("<Ahref=\"/EjemplosWeb/calculadora.html\">Volver
atrs...</A>");
out.println("</BODY>");
out.println("</HTML>");
}
catch(NumberFormatExceptionex)
{
response.sendError(500,"Algunodelosnmerosnocontenadgitos
vlidos...");
}
}
}
Nota: Recordar que los contenidos estticos como una pgina HTML se ubican dentro del
directorio /WebContent.
Al cargar la pgina en el navegador, deberamos ver algo as:
94
En caso de que no hubiramos introducido algn parmetro, o alguno de ellos llevase algn
carcter que no fuese un dgito, deberamos ver una pgina de error parecida a esta:
95
En la siguiente unidad, hablaremos un poco mas del tratamiento de errores. En este ejemplo,
hemos optado por mostrar una pgina de error HTTP, pero podramos perfectamente haber
contestado una pgina HTML al estilo de la que mostraba el resultado correcto, indicando
los motivos del error.
Aprovechando este ejemplo, vamos a comentar otro tema interesante. En la unidad donde
tratamos el protocolo HTTP, comentamos que la diferencia entre los mtodos HTTP GET y
POST era que uno enviaba los parmetros en la URL (GET) y otro en el cuerpo del mensaje
HTTP (POST). En este ejemplo, hemos utilizado el mtodo POST, pero fijaros lo que
veramos en la URL del navegador si en vez de POST hubiramos utilizado GET:
http://localhost:8080/EjemplosWeb/SumadorServlet?param1=2¶m2=8
Por eso comentbamos, que lo habitual cuando se utilizan formularios es emplear el mtodo
POST para evitar mostrar al usuario URLs farragosas, adems de que por temas de
seguridad, se intente evitar que se lea en claro una contrasea (por ejemplo).
96
Como podemos observar, tiene bastante parecido a la estructura del proyecto web dentro
de Eclipse IDE for Java EE Developers aunque no es igual. En principio, el raz del fichero
97
98
Si vamos a una sesin de DOS, mediante el comando de la JDK jar.exe (jar tvf
nombreFichero.war), podemos ver su contenido y confirmar que la estructura generada es
exactamente la de la especificacin Java EE:
99
llamamos
SumadorServlet
que
est
implementado
en
la
clase
Java
100
102
RECORDAR
destroy: se ejecuta una vez en la vida del Java Servlet y se suele utilizar para
liberar todos aquellos recursos que pudiramos haber utilizado, con el afn de
dejar el sistema lo ms limpio posible.
Los
objetos
de
los
tipos
javax.servlet.http.HttpServletRequest
103
Hemos aprendido que la principal diferencia entre las peticiones GET y POST es
que en las primeras el paso de parmetros es apreciable en la URL. Para poder
utilizar el POST, se utilizan los formularios (FORM) de HTML.
Para poder desplegar una aplicacin web, se puede realizar mediante un EAR o un
WAR (dependiendo del servidor de aplicaciones). El descriptor de despliegue
web.xml, aunque no es obligatorio si se utilizan anotaciones, conviene que exista
para poder determinar de una manera sencilla que es lo que se va a desplegar y el
comportamiento asociado.
104
Unidad de Aprendizaje 5
JAVASERVER PAGES
NDICE
5.1
5.2
5.3
5.4
5.1
Introduccin
Ya vimos en la primera unidad del curso, que los JavaServer Pages, tambin conocidos por su
acrnimo JSP, eran un tipo de componente Java EE que se empaquetaba en un mdulo web
(WAR) y se desplegaba y ejecutaba en el contenedor web de un Servidor de Aplicaciones Java
EE.
Adicionalmente, dentro del patrn de diseo MVC ocupaban el espacio de la Vista, como
encargado de mostrar el resultado de la peticin al usuario final. Es decir, al contrario que los
Java Servlets, estas estn enfocadas a la presentacin.
Repetimos, esto es un mal diseo y una mala prctica de programacin. Pero consideramos
que es imprescindible ir aprendiendo poco a poco. Por tanto, este diseo es temporal
mientras avanzamos en las sucesivas unidades del curso.
107
Por ltimo, desde un punto de vista del lenguaje de programacin Java, una JavaServer Page
no es ms que un fichero con un lenguaje de etiquetado como HTML y trozos de cdigo Java
embebidos.
5.2
Antes de entrar a estudiar en profundidad los JavaServer Pages, vamos a guiar los pasos para
desarrollar nuestro primer JavaServer Page con Eclipse IDE for Java EE Developers y
desplegarlo en Apache Tomcat. Es requisito indispensable, haber seguido los pasos de
instalacin y configuracin de ambas dos herramientas detallados en la unidad 2 de este
curso.
Estos mismos pasos nos servirn para los sucesivos ejemplos y actividades del resto del
curso.
Arrancamos Eclipse IDE for Java EE Developers y mediante el las opciones de men File ->
New -> Dynamic Web Project:
108
En la ltima ventana del asistente, antes de pulsar el botn Finish, nos aseguramos de
marcar la opcin Generate web.xml deployment descriptor:
109
110
111
En la siguiente ventana, rellenamos el nombre del fichero (File name) con HolaMundo.jsp.
Nos aseguraremos de que el directorio donde se va a crear sea /WebContent (normalmente se
selecciona por defecto). Y pulsamos el botn Finish:
112
Ya solo queda, probar la aplicacin. Para ello, pulsamos el botn derecho sobre el fichero JSP
-> Run As -> Run on Server:
114
En la vista de Console veremos las trazas que va dejando el Servidor de Aplicaciones Java
EE al arrancar, cmo despliega la aplicacin y automticamente abre un navegador interno de
Eclipse IDE con la URL: http://localhost:8080/HolaMundoWeb/HolaMundo.jsp donde se ve el
resultado de nuestro primer JavaServer Page:
115
Perfectamente podramos utilizar otro navegador web (tipo Mozilla Firefox o Internet Explorer)
y escribir la misma URL. El comportamiento debera ser el mismo.
Para abrir el navegador interno de Eclipse IDE a mano, utilizar el botn de la barra de
herramientas:
Ya solo nos queda desinstalar la aplicacin mediante la opcin Add and Remove:
116
117
5.3
JavaServer Pages
Una JavaServer Page, es un fichero de extensin *.jsp que utiliza principalmente lenguajes de
etiquetado como el HTML (estudiado en la unidad 3) u otros menos extendidos como WML,
SVG, cHTML, etc, en el que se pueden embeber mediante unas etiquetas especiales, cdigo
Java.
Es decir, vendran a ser como el opuesto de los Java Servlets. Si aquellos eran cdigo Java
con cdigo de etiquetado embebido en las sentencias de escritura, estas son cdigo de
etiquetado con cdigo Java embebido.
A la hora de su ejecucin, el Servidor Java EE convertir estos ficheros en un Java Servlet
como los estudiados en la unidad anterior. Es decir, generar de forma automtica, un Java
Servlet en el que incluir todos los fragmentos de Java embebidos, y aadir sentencias de
impresin con el lenguaje de etiquetado de presentacin esttico.
Aunque como decimos, este proceso ocurre a sin conocimiento directo del desarrollador y lo
realiza automticamente el Servidor de Aplicaciones Java EE, siempre va bien tenerlo en
118
119
Un uso habitual de los scriptlets que dota de gran potencia y dinamismo a las JavaServer
Pages, es su integracin con el etiquetado de presentacin. Por ejemplo:
<%
if(sexo.equals(Hombre))
{
%>
<H1>Buenosdasseor</H1>
<%
}
else
{
%>
<H1>Buenosdasseora</H1>
<%
}
%>
Como podemos observar, hemos conseguido dotar de dinamismo al lenguaje HTML que por
su naturaleza es esttico. Dependiendo del valor de una variable, la etiqueta HTML que se
enva al cliente como parte de la respuesta es una u otra.
Igual que hemos utilizado una bifurcacin, pensad en la flexibilidad que nos da poder usar
tambin un bucle para alimentar listas o tablas de forma dinmica.
122
{
%>
<FORMmethod="POST"action="/EjemplosWeb/calculadora.jsp">
<INPUTtype="hidden"name="switch"value="true">
<TABLEborder="0">
<TR>
<TD>Primernmero:</TD>
<TD><INPUTname="param1"></TD>
</TR>
<TR>
<TD>Segundonmero:</TD>
<TD><INPUTname="param2"></TD>
</TR>
<TR>
<TD><INPUTtype="submit"value="Sumar"></TD>
</TR>
</TABLE>
</FORM>
<%
}
else
{
try
{
intparam1=Integer.parseInt(request.getParameter("param1"));
intparam2=Integer.parseInt(request.getParameter("param2"));
intresult=param1+param2;
%>
Elresultadodelasumaes:<%=sumar(param1,param2)%><BR><BR>
<%
}
catch(NumberFormatExceptionex)
{
%>
123
Algunodelosnmerosnocontenadgitosvlidos...<BR><BR>
<%
}
%>
<%=Calendar.getInstance().getTime()%><BR><BR>
<Ahref="/EjemplosWeb/calculadora.jsp">Volveratrs...</A>
<%
}
%>
</BODY>
</HTML>
Si analizamos detenidamente el ejemplo, podemos observar el uso de los distintos tipos de
etiquetado:
Directivas para definir algunos aspectos tcnicos de la JavaServer Page, as como
aadir imports necesarios para la correcta compilacin.
Comentarios para documentar el objetivo del mtodo sumar.
Declaraciones para definir el mtodo sumar.
Scriptlets para implementar la lgica de control.
Expresiones para devolver los valores calculados.
Evidentemente se trata de un ejemplo, donde hemos intentado utilizar el 100% de los
conceptos expuestos. No quiere decir que la mejor solucin implique utilizarlos todos.
Por cierto, algn lector se habr dado cuenta de la utilizacin de un objeto request sin
haberlo mencionado ni definido en ningn sitio. Las JavaServer Pages cuentan con una serie
de objetos implcitos accesibles desde cualquier punto de la pgina. Los comentaremos en
la siguiente seccin.
Adicionalmente, y simplemente a modo ilustrativo, adjuntamos el cdigo fuente del Java
Servlet que el Servidor de Aplicaciones Java EE habra generado para la JavaServer Page de
ejemplo. Como decimos, es puramente a modo ilustrativo, por si puede ayudar a entender
los conceptos explicados. Recordar que la generacin y compilacin de este Java Servlet es
algo automtico e intrnseco del Servidor de Aplicaciones Java EE:
/*
*GeneratedbytheJaspercomponentofApacheTomcat
*Version:ApacheTomcat/7.0.22
*Generatedat:2012021712:25:10UTC
*Note:Thelastmodifiedtimeofthisfilewassetto
*thelastmodifiedtimeofthesourcefileafter
*generationtoassistwithmodificationtracking.
*/
packageorg.apache.jsp;
importjavax.servlet.*;
importjavax.servlet.http.*;
importjavax.servlet.jsp.*;
importjava.util.Calendar;
124
publicintsumar(intparam1,intparam2)
{
returnparam1+param2;
}
privatestaticfinaljavax.servlet.jsp.JspFactory_jspxFactory=
javax.servlet.jsp.JspFactory.getDefaultFactory();
privatestaticjava.util.Map<java.lang.String,java.lang.Long>
_jspx_dependants;
privatejavax.el.ExpressionFactory_el_expressionfactory;
privateorg.apache.tomcat.InstanceManager_jsp_instancemanager;
publicjava.util.Map<java.lang.String,java.lang.Long>
getDependants(){
return_jspx_dependants;
}
publicvoid_jspInit(){
_el_expressionfactory=
_jspxFactory.getJspApplicationContext(getServletConfig().getServletCon
text()).getExpressionFactory();
_jsp_instancemanager=
org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(ge
tServletConfig());
}
publicvoid_jspDestroy(){
}
publicvoid_jspService(finaljavax.servlet.http.HttpServletRequest
request,finaljavax.servlet.http.HttpServletResponseresponse)
throwsjava.io.IOException,javax.servlet.ServletException{
finaljavax.servlet.jsp.PageContextpageContext;
javax.servlet.http.HttpSessionsession=null;
finaljavax.servlet.ServletContextapplication;
finaljavax.servlet.ServletConfigconfig;
javax.servlet.jsp.JspWriterout=null;
finaljava.lang.Objectpage=this;
javax.servlet.jsp.JspWriter_jspx_out=null;
javax.servlet.jsp.PageContext_jspx_page_context=null;
try{
response.setContentType("text/html;charset=ISO88591");
pageContext=_jspxFactory.getPageContext(this,request,
response,null,true,8192,true);
_jspx_page_context=pageContext;
application=pageContext.getServletContext();
config=pageContext.getServletConfig();
session=pageContext.getSession();
out=pageContext.getOut();
_jspx_out=out;
out.write("\r\n");
out.write("\r\n");
125
out.write("<!DOCTYPEhtmlPUBLIC\"//W3C//DTDHTML4.01
Transitional//EN\"
\"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
out.write("<HTML>\r\n");
out.write("<HEAD>\r\n");
out.write("<METAhttpequiv=\"ContentType\"
content=\"text/html;charset=ISO88591\">\r\n");
out.write("<TITLE>Calculadora</TITLE>\r\n");
out.write("</HEAD>\r\n");
out.write("<BODY>\r\n");
out.write("");
out.write("\r\n");
out.write("");
out.write("\r\n");
out.write("\t");
if(request.getParameter("switch")==null)
{
out.write("\r\n");
out.write("\t<FORMmethod=\"POST\"
action=\"/EjemplosWeb/calculadora.jsp\">\r\n");
out.write("\t\t<INPUTtype=\"hidden\"name=\"switch\"
value=\"true\">\r\n");
out.write("\t\t<TABLEborder=\"0\">\r\n");
out.write("\t\t\t<TR>\r\n");
out.write("\t\t\t\t<TD>Primernmero:</TD>\r\n");
out.write("\t\t\t\t<TD><INPUTname=\"param1\"></TD>\r\n");
out.write("\t\t\t</TR>\r\n");
out.write("\t\t\t<TR>\r\n");
out.write("\t\t\t\t<TD>Segundonmero:</TD>\r\n");
out.write("\t\t\t\t<TD><INPUTname=\"param2\"></TD>\r\n");
out.write("\t\t\t</TR>\r\n");
out.write("\t\t\t<TR>\r\n");
out.write("\t\t\t\t<TD><INPUTtype=\"submit\"
value=\"Sumar\"></TD>\r\n");
out.write("\t\t\t</TR>\r\n");
out.write("\t\t</TABLE>\r\n");
out.write("\t</FORM>\r\n");
out.write("\t");
else
try
intparam1=Integer.parseInt(request.getParameter("param1"));
intparam2=Integer.parseInt(request.getParameter("param2"));
out.write("\r\n");
out.write("\tElresultadodelasumaes:");
out.print(sumar(param1,param2));
out.write("<BR><BR>\r\n");
out.write("\t");
catch(NumberFormatExceptionex)
{
out.write("\r\n");
out.write("\tAlgunodelosnmerosnocontenadgitos
vlidos...<BR><BR>\r\n");
out.write("\t");
}
out.write('\r');
out.write('\n');
126
5.4
Otros conceptos
En este apartado trataremos algunos otros conceptos relacionados con los JavaServer Pages
que ya hemos mencionado pero no hemos tratado con el suficiente detalle.
128
Como podemos observar, tiene bastante parecido a la estructura del proyecto web dentro
de Eclipse IDE for Java EE Developers aunque no es igual. En principio, el raz del fichero
WAR correspondera al directorio /WebContent y el directorio /classes del fichero WAR
correspondera al directorio /build/classes.
129
130
Si vamos a una sesin de DOS, mediante el comando de la JDK jar.exe (jar tvf
nombreFichero.war), podemos ver su contenido y confirmar que la estructura generada es
exactamente la de la especificacin Java EE:
131
133
PARA RECORDAR
Dentro del patrn de diseo MVC ocupan el espacio de la Vista, como encargado
de mostrar el resultado de la peticin al usuario final. Estn enfocadas a la
presentacin.
Scriptles: <% %> para incluir cdigo Java embebido en la JavaServer Page.
El ciclo de vida de una JavaServer Page es similar a los Java Servlets, solo que
cambian los nombres, jspInit, jspService y jspDestroy
134
135
136
Unidad de Aprendizaje 6
DISEO DE APLICACIONES
JAVA EE
NDICE
6.1
6.2
6.3
6.1
Introduccin
Llegados a este punto, el alumno ya conoce lo bsico de las tecnologas Java Servlet y
JavaServer Page (JSP), sus pros y contras, puntos fuertes y puntos flojos.
En ms de una ocasin durante las ltimas unidades, hemos comentado que estbamos
haciendo un mal diseo de las aplicaciones pero que desde un punto de vista didctico nos
pareca conveniente hacerlo as, para comprender mejor esta unidad dedicada al diseo de
Aplicaciones Java EE.
Existen multitud de patrones de diseo relacionados con las Aplicaciones Java EE, pero hay
uno ya mencionado durante el curso que tiene en cuenta a la aplicacin en su conjunto y no a
una parte solo.
Estamos hablando del patrn MVC (Modelo-Vista- Controlador o Model-View-Controller en
ingls).
Este patrn de diseo divide la aplicacin en tres roles, cada uno de ellos con unas
responsabilidades muy concretas.
El Modelo (Model): Representa los datos y cualquier lgica de negocio relacionada con
ellos.
139
Pues bien, los dos tipos de componentes Java EE que hemos estudiado ya, encajan
perfectamente en este diseo:
Controlador: Java Servlets.
Vista: JavaServer Pages (JSP).
6.1.1 El Controlador
De la experiencia que hemos cogido con las actividades relacionadas con la unidad de los
Java Servlets, hemos visto que son muy potentes para contener cdigo Java, analizar los
parmetros de las peticiones, validarlos, manipularlos, etc pero sin embargo son
realmente tediosos para manejar la presentacin. Para un diseador grfico de pginas
HTML, es realmente complicado crear y mantener dichas pginas a travs de lneas
out.println(.) que dificultan ver el resultado final en su conjunto.
6.1.2 La Vista
Por el contrario, los JavaServer Pages (JSP) han demostrado ser muy valiosos para realizar
el diseo grfico de la presentacin, insertando pequeos scriptlets Java, pero muy tediosos
cuando el nmero de lneas de cdigo Java se incrementa y entonces la mezcla de lgica y
presentacin se hace muy complicada.
140
141
6.2
Quedan claras entonces las interrelaciones que existirn entre los distintos componentes
estudiados. Pero tcnicamente cmo hacemos dichos enlaces?
La invocacin desde un Java Servlet a un JavaBean (o POJO) es muy sencilla. Simplemente
instanciar la clase en cuestin e invocar algn mtodo de la misma. Pero, y la invocacin
desde un Java Servlet a un JavaServer Page (JSP)?
Dicha invocacin se realiza mediante el interface javax.servlet.RequestDispatcher.
6.2.1 RequestDispatcher
Una instancia del tipo RequestDispatcher, representa la informacin necesaria para lanzar
una peticin a un recurso web. En nuestro caso, podremos lanzar una peticin a otro Java
Servlet o un JavaServer Page (JSP).
El acceso a dicha instancia se puede realizar mediante el mtodo:
RequestDispatcher getRequestDispatcher(java.lang.String path);
de la HttpServletRequest, donde el parmetro que necesita, indica el recurso al que
queremos acceder.
RequestDispatcher tiene dos mtodos:
void forward(ServletRequest request, ServletResponse response) throws.
Este primer mtodo, nos permite redirigir la peticin a otro componente y delegar en l
la respuesta. Es decir, el control de lo que se responde al cliente por parte del Servidor
Java EE queda delegado.
void include(ServletRequest request, ServletResponse response) throws.
Este segundo mtodo nos permite incluir como parte de nuestra respuesta, la
respuesta de otro componente. Es decir, dicho componente colabora con la
respuesta, pero el control lo seguimos teniendo nosotros. Es el mismo resultado que la
directiva JSP include que estudiamos en la unidad anterior.
Los parmetros de ambos mtodos son la peticin y respuesta HTTP. Normalmente sern
los mismos que hemos recibido.
Por tanto, ya sabemos cmo redirigir la ejecucin desde un Java Servlet a un JavaServer
Page (JSP). Pero nos quedara un tema pendiente. Cmo le pasamos informacin de la
lgica de negocio al siguiente?
Existen varias maneras de hacerlo:
A travs de la HttpServletRequest. Podemos utilizar los mtodos setParameter() o
setAttribute() de la peticin para aadir informacin que ser utilizada por el
siguiente componente de la aplicacin mediante los correspondientes mtodos
getParameter() o getAttribute().
A travs de la HttpSession. Todava no hemos estudiado este concepto. Lo trataremos
en la siguiente unidad.
142
<FORMmethod="POST"action="/EjemplosWeb/RestadorServlet">
<TABLEborder="0">
<TR>
<TD>Primernmero:</TD>
<TD><INPUTname="param1"></TD>
</TR>
143
<TR>
<TD>Segundonmero:</TD>
<TD><INPUTname="param2"></TD>
</TR>
<TR>
<TD><INPUTtype="submit"value="Restar"></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
JavaBean o POJO (Modelo) RestadorBean.java:
packagees.aulamentor;
publicclassRestadorBean
{
publicintrestar(intparam1,intparam2)
{
returnparam1+param2;
}
}
Java Servlet (Controlador) index.jsp:
packagees.aulamentor;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet(name="RestadorServlet",urlPatterns={"/RestadorServlet"})
publicclassRestadorServletextendsHttpServlet
{
protectedvoiddoGet(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
this.procesarPeticion(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
this.procesarPeticion(request,response);
}
privatevoidprocesarPeticion(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
try
{
intparam1=
Integer.parseInt(request.getParameter("param1"));
144
intparam2=
Integer.parseInt(request.getParameter("param2"));
RestadorBeanrestadorBean=newRestadorBean();
intresult=restadorBean.restar(param1,param2);
request.setAttribute("result",result);
request.getRequestDispatcher("/result.jsp").forward(reques
t,response);
}
catch(NumberFormatExceptionex)
{
request.setAttribute("error","Algunodelosnmerosno
contenadgitosvlidos...");
request.getRequestDispatcher("/error.jsp").forward(request
,response);
}
}
<Ahref="/EjemplosWeb/index.jsp">Volveratrs...</A>
</BODY>
</HTML>
No es necesario utilizar un descriptor de despliegue, ya que en el Java Servlet hicimos uso
de las Anotaciones Java.
Si el alumno implementa este ejemplo, debera ver algo as
Pgina de inicio:
Pgina de resultado:
146
6.3
A lo largo de la vida de las especificaciones Java EE, se han ido definiendo distintos patrones
de diseo (buenas prcticas) que han demostrado ser muy tiles por distintos motivos tanto en
el desarrollo como en el mantenimiento de las aplicaciones web.
Existe mucha literatura sobre el tema, aunque la gua bsica es la denominada Java EE
BluePrints:
http://java.sun.com/blueprints/patterns/
Este curso no pretende entrar a estudiar en profundidad los distintos patrones, pero si que
comentaremos y utilizaremos alguno adicional que resultan interesantes
A continuacin, listamos alguno sencillo de entender y de mucha utilidad:
Data Access Object, tambin llamado DAO (u Objeto de Acceso a Datos): permite
abstraer a la lgica de negocio del sistema de persistencia de los datos. Seguramente
a muchos os sonar de cuando estudiasteis el acceso a Bases de Datos con Java:
JDBC (Java DataBase Access). Es decir, la lgica de la aplicacin es agnstica de si
estamos usando Bases de Datos, ficheros, o cualquier otra frmula de persistencia y
acceso a los datos. Nuevamente, un cambio en la forma de hacerlo, solo afectara al
Data Access Object pero no a la lgica de negocio.
Tendremos oportunidad de utilizarlo en los ejemplos y actividades de las siguientes
unidades.
Ms informacin en:
http://www.oracle.com/technetwork/java/dao-138818.html
Intercepting Filter (o Filtro Interceptor): permite implementar una lgica que se ejecute
siempre previamente a recibir una peticin y posteriormente a enviar la respuesta.
Imaginemos por ejemplo que queremos incluir en nuestra aplicacin un sistema de
logging, o de autenticacin, etc
Tcnicamente se implementa mediante unos Java Servlets especiales denominados
filtros que estudiaremos en la siguiente unidad.
Ms informacin en:
http://www.oracle.com/technetwork/java/interceptingfilter-136585.html
148
149
PARA RECORDAR
En esta unidad hemos visto detalladamente que componentes son los adecuados a
utilizar siguiendo el patrn de diseo MVC:
El Modelo: Representa los datos y cualquier lgica de negocio relacionada con
ellos. Implementado mediante POJOS (tambin EJBs).
La Vista: Renderiza el contenido de los modelos dependiendo de la tipologa de
cliente (navegador web, telfono mvil, etc). Implementado mediante
JavaServer Pages (JSP).
El Controlador: Define el comportamiento general de la aplicacin coordinando
a las otras dos partes (Modelo y Vista). Implementado mediante Java Servlets.
La conexin entre un Java Servlet y un POJO se realiza mediante las llamadas a los
mtodos de dicho componente.
Para pasarle los datos necesarios del Java Servlet y un JavaServer Page (JSP) se
pueden utilizar los siguiente mecanismos:
HttpServletRequest. Podemos
setAttribute() de la peticin
utilizar
los
mtodos
setParameter()
HttpSession.
ServletContext.
Front Controller: se trata de una pieza controladora que centraliza todas las
peticiones y va eligiendo qu lgica de negocio y presentacin son necesarias para
dicha peticin.
Intercepting Filter: permite implementar una lgica que se ejecute siempre
previamente a recibir una peticin y posteriormente a enviar la respuesta.
Service Locator: permite simplificar el acceso a servicios de la aplicacin o del
Servidor de Aplicaciones Java encapsulando dicha bsqueda y permitiendo su
reutilizacin.
Transfer Object: permite encapsular la informacin que viaja entre las distintas
capas de la aplicacin
151
152
Unidad de Aprendizaje 7
NDICE
7.1
7.2
7.3
7.4
7.5
Filtros............................................................................. 175
7.6
7.7
7.1
Introduccin
A estas alturas del curso, ya hemos aprendido las tecnologas bsicas sobre las que se apoya
el desarrollo de aplicaciones web Java EE y cundo usar unas u otras. Incluso ya hemos
desarrollado algunas aplicaciones sencillas.
El objetivo de las siguientes unidades, es profundizar en estas tecnologas para poderle sacar
ms provecho y llegar a desarrollar aplicaciones Java EE reales.
7.2
Como bien recordars de las unidades anteriores, el ciclo de vida de un Java Servlet tena un
mtodo de inicializacin:
public void init(ServletConfig config);
que se ejecutaba una sola vez al inicio de la vida del Java Servlet y que se sola utilizar para
llevar a cabo todas las labores de inicializacin y configuracin que necesitramos para su
posterior ejecucin.
Como
se
puede
observar,
javax.servlet.ServletConfig,
que
recibe
como
representa
parmetro
la
una
informacin
de
instancia
de
configuracin
la
clase
que
el
java.util.Enumeration<java.lang.String> getInitParameterNames()
Devuelve una coleccin con los nombres de todos los parmetros de configuracin
que tiene.
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>ConfigServlet</servletname>
<servletclass>es.aulamentor.ConfigServlet</servletclass>
<initparam>
<paramname>param1</paramname>
<paramvalue>Hola</paramvalue>
</initparam>
<initparam>
<paramname>param2</paramname>
<paramvalue>Mundo</paramvalue>
</initparam>
</servlet>
<servletmapping>
<servletname>ConfigServlet</servletname>
<urlpattern>/ConfigServlet</urlpattern>
</servletmapping>
</webapp>
importjava.io.IOException;
importjava.util.Enumeration;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebInitParam;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet(name="ConfigServlet",urlPatterns={"/ConfigServlet"},
initParams={@WebInitParam(name="param1",value="Hola"),
@WebInitParam(name="param2",value="Mundo")})
publicclassConfigServletextendsHttpServlet
{
publicvoidinit(ServletConfigconfig)throwsServletException
{
Enumeration<String>parameters=config.getInitParameterNames();
while(parameters.hasMoreElements())
{
Stringname=parameters.nextElement();
156
protectedvoiddoGet(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,
IOException
{
}
}
Este cdigo de ejemplo en ejecucin dentro del entorno de desarrollo mostrara algo as:
Ambos dos mtodos no son excluyentes, aunque no tiene mucho sentido utilizar ambos para
un mismo Java Servlet. No obstante, si as fuera y en el hipottico caso de que en ambos dos
sitios existiera un parmetro con el mismo nombre, tendra prioridad el del descriptor de
despliegue.
157
7.3
Nota: En esta seccin se asume que el alumno tiene conceptos de programacin avanzada en
Java, en concreto, en la programacin concurrente con Java Threads.
Se dice que una aplicacin soporta concurrencia cuando permite ejecuciones en paralelo de
su cdigo. Es decir, en el caso de las aplicaciones Java EE que estamos estudiando,
significara que varios usuarios puedan conectarse y ejecutar la aplicacin a la vez.
Las aplicaciones Java EE son concurrentes por naturaleza. El Servidor de Aplicaciones Java
EE se encarga de controlar y permitir la concurrencia de la aplicacin permitiendo al
desarrollador prcticamente despreocuparse de esta casustica.
Teniendo en cuenta que solamente hay una instancia de un Java Servlet por cada JVM, no
debemos olvidarnos nunca del tema y tenerlo siempre presente en nuestros desarrollos para
evitar problemas y comportamientos no deseados. Por ejemplo, imaginemos lo que puede
ocurrir si utilizamos variables de instancia en el Java Servlet para manejar una informacin
temporal durante la ejecucin de un mtodo, en el que hemos sustituido un posible cdigo
que tarda cierto tiempo en ejecutar por un Thread.sleep(5000);
packagees.aulamentor;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet("/ConcurrenciaServlet")
publicclassConcurrenciaServletextendsHttpServlet
{
privateintval=0;
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,IOException
{
val=Integer.parseInt(request.getParameter("param"));
System.out.println("Thread:"+Thread.currentThread().getName()+
"usaelvalor:"+val);
try
{
//Simulamosqueelservletestconalgunaoperativaantesde
//volverautilizarelvalordelavariableval.
Thread.sleep(5000);
}
catch(InterruptedExceptionex)
{
}
System.out.println("Thread:"+Thread.currentThread().getName()+
"usaelvalor:"+val);
}
}
E invocamos desde el navegador a este Java Servlet dos veces consecutivas (en menos de 5
segundos) primero con el parmetro 5 y luego con el parmetro 2:
158
La primera peticin la sirve un thread controlado por el Servidor de Aplicaciones Java EE que
se llama http-bio-8080-exec3 y el inicio de la ejecucin del Java Servlet muestra que el
parmetro con el que tiene que trabajar vale 5. Entonces, se duerme durante 5 segundos (ha
sido la forma de simular una tarea costosa) y cuando vuelve a por el parmetro, resulta que
vale 2.
Qu ha pasado? Lo que ha pasado es que antes de que el primer Java Servlet terminara de
ejecutarse, el Servidor de Aplicaciones Java EE recibi una segunda peticin al mismo Java
Servlet con un valor del parmetro distinto. Como ambos dos threads, en este caso http-bio8080-exec-4, ejecutan el mismo cdigo, el segundo ha machacado el valor al primero.
Se trata de un ejemplo muy sencillo, pero el problema que demuestra puede ser muy
complicado de detectar.
Existen distintas soluciones:
159
7.4
Nota: En esta seccin se asume que el alumno tiene conceptos de programacin avanzada en
Java, en concreto, en la programacin de acceso a Bases de Datos con JDBC.
Existen distintas alternativas para el acceso a Bases de Datos desde aplicaciones web. Vamos
a comentar dos de ellas: mediante el acceso directo a la Base de Datos desde el cdigo y
mediante un servicio que nos proveen los Servidores de Aplicaciones Java EE denominado
Pool de Conexiones (o Data Source).
La primera alternativa tiene bastantes problemas (uno de ellos es que tiene peor rendimiento
que las otras alternativas) y no es para nada recomendada. Pero, no obstante, la veremos
brevemente para entender mejor la naturaleza de una aplicacin web, el por qu esta es una
mala alternativa y cmo la segunda es una opcin mucho mejor.
160
importjava.io.IOException;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
161
importjava.sql.SQLException;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet("/BaseDatosServlet")
publicclassBaseDatosServletextendsHttpServlet
{
publicvoidinit(ServletConfigconfig)throwsServletException
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
}
catch(ClassNotFoundExceptionex)
{
System.out.println("DriverJDBCnoencontrado...");
ex.printStackTrace();
}
}
protectedvoiddoPost(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
Connectioncon=null;
PreparedStatementpstmt=null;
ResultSetrs=null;
Stringisbn=request.getParameter("isbn");
try
{
con=DriverManager.getConnection("jdbc:derby:D:/biblioteca",
"derbyuser","derbyuser");
pstmt=con.prepareStatement("SELECT*FROMPRESTAMOSWHEREISBN
=?");
pstmt.setString(1,isbn);
rs=pstmt.executeQuery();
if(rs.next())
{
request.setAttribute("titulo",rs.getString(3));
}
request.getRequestDispatcher("/resultDB.jsp").forward(request,
response);
}
catch(SQLExceptionex)
{
System.out.println("ProblemasenelaccesoalaBD...");
ex.printStackTrace();
}
finally
{
try
{
if(rs!=null)
rs.close();
}
catch(SQLExceptionex)
162
163
En esta ocasin, nuestra aplicacin est haciendo uso de los Drivers JDBC de una Base de
Datos (en concreto de Apache Derby) por lo que tendremos que tener en cuenta aadir el
fichero JAR que contiene dichas clases Java en nuestra aplicacin.
La estructura de un mdulo Web segn las especificaciones Java EE dictaba que este tipo
de ficheros deban ubicarse en el directorio /WEB-INF/lib, que en un proyecto web de
Eclipse IDE for Java EE Developers corresponde a /WebContent/WEB-INF/lib:
Otra opcin sera aadir el fichero a la instalacin del Servidor de Aplicaciones Java EE en
vez de aadirlo a cada mdulo web que acceda a la Base de Datos.
La configuracin de esta opcin es dependiente del servidor, es decir, dependiendo del
servidor que estemos utilizando se har de una manera u otra. En nuestro caso, que
estamos utilizando Apache Tomcat 7.0.x, el fichero JAR se debe copiar en el directorio /lib
de la instalacin:
164
Pgina de resultado:
165
No obstante, como ya hemos comentado, esta forma de acceder a Bases de Datos tiene
graves problemas de rendimiento en el caso de tener muchos usuarios y adems, si
decidimos compartir la conexin y la sentencia a travs de una variable de instancia (o
atributo) para mejorar algo el rendimiento, tenemos que introducir en la programacin
tcnicas de sincronizacin que no son triviales.
Por este motivo, las especificaciones Java EE definieron el concepto de Pool de Conexiones
(Data Source) que todo Servidor de Aplicaciones Java EE debe implementar y que
estudiaremos a continuacin.
name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="derbyuser"
password="derbyuser"
167
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby:D:/biblioteca"/>
tipo
de
interface
que
implementa
el
recurso
(en
nuestro
caso
javax.sql.DataSource).
username: identificador de usuario en el caso de que el Gestor de Base de Datos que
estamos utilizando tenga la seguridad activada.
password: contrasea de usuario en el caso de que el Gestor de Base de Datos que
estamos utilizando tenga la seguridad activada.
driverClassName: nombre del Driver JDBC de acceso al Gestor de Base de Datos
que estamos utilizando.
url: URL JDBC.
El resto de propiedades suelen estar relacionadas con las caractersticas ms funcionales
del Pool de Conexiones, temas como el nmero mximo de conexiones que puede tener, el
tiempo mximo que una conexin puede estar asignada sin ser devuelta al pool, etc
Con esto, el Servidor de Aplicaciones Java EE ya va a crear y gestionar un Pool de
Conexiones con nuestra Base de Datos. Ahora, nos queda indicar que nuestra aplicacin
web est interesada en el acceso a dicho pool y lo haremos mediante el descriptor de
despliegue del mdulo web (web.xml).
Para ello, aadiremos el siguiente bloque resource-ref:
<resourceref>
<description>ConexionBD</description>
<resrefname>jdbc/TestDB</resrefname>
<restype>javax.sql.DataSource</restype>
<resauth>Container</resauth>
</resourceref>
Simplemente hacemos referencia al recurso creado y configurado en el servidor,
identificando bsicamente el nombre (res-ref-name) y tipo (res-type). De esta manera, al
desplegar la aplicacin web, el Servidor de Aplicaciones Java EE nos dar acceso al
recurso.
Ya solo nos queda modificar el cdigo fuente de nuestra aplicacin para que ahora haga uso
del Data Source en vez de crear las conexiones a la Base de Datos directamente.
168
en
el
servidor,
etc)
se
producir
una
excepcin
pueden estar accediendo a la Base de Datos en paralelo, no como antes que el acceso era
sincronizado (y por tanto serializado) a una nica conexin.
No obstante, al igual que cuando accedamos directamente a la Base de Datos desde el
cdigo, es importante liberar los recursos cuando se han dejado de utilizar. En este caso, la
diferencia es que la llamada al mtodo close de la conexin, en vez de cerrarla lo que hace
es devolverla al Pool de Conexiones como disponible para poder ser utilizada por otra
peticin.
Veamos la aplicacin de ejemplo de antes, pero esta vez utilizando un Pool de Conexiones.
Descriptor de despliegue:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>DataSourceServlet</servletname>
<servletclass>es.aulamentor.DataSourceServlet</servletclass>
</servlet>
<servletmapping>
<servletname>DataSourceServlet</servletname>
<urlpattern>/DataSourceServlet</urlpattern>
</servletmapping>
<resourceref>
<description>ConexionBD</description>
<resrefname>jdbc/TestDB</resrefname>
<restype>javax.sql.DataSource</restype>
<resauth>Container</resauth>
</resourceref>
</webapp>
Pgina HTML de inicio:
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>AccesoaBasesdeDatos</TITLE>
</HEAD>
<BODY>
<FORMmethod="POST"action="/EjemplosWeb/DataSourceServlet">
<TABLEborder="0">
<TR>
<TD>IntroduzcaelISBN:</TD>
<TD><INPUTname="isbn"></TD>
</TR>
<TR>
<TD><INPUTtype="submit"value="Buscar"></TD>
</TR>
</TABLE>
</FORM>
170
importjava.io.IOException;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importjavax.naming.Context;
importjavax.naming.InitialContext;
importjavax.naming.NamingException;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjavax.sql.DataSource;
publicclassDataSourceServletextendsHttpServlet
{
DataSourcedatasource=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
try
{
ContextinitialContext=newInitialContext();
datasource=
(DataSource)initialContext.lookup("java:comp/env/jdbc/TestDB");
}
catch(NamingExceptionex)
{
System.out.println("ProblemasenelaccesoalaBasede
Datos...");
ex.printStackTrace();
}
}
protectedvoiddoPost(HttpServletRequestrequest,
HttpServletResponseresponse)throwsServletException,IOException
{
Connectioncon=null;
PreparedStatementpstmt=null;
ResultSetrs=null;
Stringisbn=request.getParameter("isbn");
try
{
con=datasource.getConnection();
pstmt=con.prepareStatement("SELECT*FROMPRESTAMOSWHEREISBN
=?");
pstmt.setString(1,isbn);
rs=pstmt.executeQuery();
if(rs.next())
{
request.setAttribute("titulo",rs.getString(3));
171
}
request.getRequestDispatcher("/resultDS.jsp").forward(request,
response);
}
catch(SQLExceptionex)
{
System.out.println("ProblemasenelaccesoalaBasede
Datos...");
ex.printStackTrace();
}
finally
{
try
{
if(rs!=null)
rs.close();
}
catch(SQLExceptionex)
{
ex.printStackTrace();
}
try
{
if(pstmt!=null)
pstmt.close();
}
catch(SQLExceptionex)
{
ex.printStackTrace();
}
try
{
if(con!=null)
con.close();
}
catch(SQLExceptionex)
{
ex.printStackTrace();
}
}
}
}
Pgina JSP de resultado:
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>AccesoaBasesdeDatos</TITLE>
</HEAD>
<BODY>
<%
if(request.getAttribute("titulo")!=null)
{
%>
Elttulodellibroes:<%=request.getAttribute("titulo")%>
172
Pgina de resultado:
173
Ahora bien, como ya hemos comentado en otras ocasiones, a partir de Java EE 6.0 existe
otra alternativa al descriptor de despliegue y cdigo Java. Son las anotaciones Java.
Veamos cmo quedara el mismo ejemplo usando la anotacin @Resource. En vez de
escribir las lneas de cdigo necesarias para realizar la bsqueda:
publicclassDataSourceServletextendsHttpServlet
{
DataSourcedatasource=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
try
{
ContextinitialContext=newInitialContext();
datasource=
(DataSource)initialContext.lookup("java:comp/env/jdbc/TestDB");
}
catch(NamingExceptionex)
{
System.out.println("ProblemasenelaccesoalaBD...");
ex.printStackTrace();
}
}
podramos simplemente usar esta anotacin:
publicclassDataSourceServletextendsHttpServlet
{
@Resource(name="java:comp/env/jdbc/TestDB")
DataSourcedatasource;
teniendo en cuenta importar el paquete: javax.annotation;
Cualquiera de las dos opciones es vlida.
Adicionalmente, existe otra anotacin muy til sobre todo para los entornos de desarrollo
locales que permite realizar la definicin de los DataSources sin necesidad de tocar los
ficheros de configuracin de los Servidores de Aplicacin Java EE. Es mediante la anotacin
@DataSourceDefinition que requiere importar el paquete: javax.annotation.sql;
Nota: esta opcin no est disponible en el servidor Apache Tomcat 7.0.x que utilizamos en
este curso (que como recordaremos, no implementaba el 100% de las especificaciones Java
EE, sola las relacionadas con la capa web), pero no obstante la comentamos:
@DataSourceDefinition(name="java:comp/env/jdbc/TestDB",className=
"org.apache.derby.jdbc.EmbeddedDriver",url=
"jdbc:derby:D:/biblioteca")
publicclassDataSourceServletextendsHttpServlet
{
@Resource(name="java:comp/env/jdbc/TestDB")
DataSourcedatasource;
174
7.5
Filtros
Un filtro es un componente web ms, que a diferencia de los que hemos visto hasta ahora no
son invocados directamente. Son unos componentes que se despliegan como parte de la
aplicacin Web, y cuya misin es interceptar las peticiones y respuesta de un componente
concreto para por ejemplo, realizar algn tipo de validacin, algn tipo de auditoria, algn tipo
de transformacin, etc
Es decir, sin que el usuario lo sepa, antes y despus de la ejecucin de un componente web
se ejecuta este nuevo componente.
Un filtro de implementar el interface: javax.servlet.Filter que incluye tres mtodos:
Se invoca una nica vez en la vida del filtro y se utiliza para realizar las labores de
inicializacin. El parmetro del tipo javax.servlet.FilterConfig da acceso a cualquier
atributo de configuracin del filtro que se haya especificado en el descriptor de
despliegue o en las anotaciones.
void destroy();
175
Nuevamente, se invoca una nica vez en la vida del filtro y se utiliza para realizar las
labores de limpieza y liberacin de recursos si fuese necesario.
Como vemos, es muy parecido a un Java Servlet con la diferencia de que no son invocados
expresamente por la presentacin, sino que se ejecutan cuando el componente web al que
filtran es invocado.
Desde la aparicin de Java EE 6.0 existen dos maneras de declarar los filtros y asociarlos a
unos componentes web determinados: el descriptor de despliegue y las anotaciones Java.
Veamos primero cmo se definen y configuran en el descriptor de despliegue, el fichero
web.xml
Definimos el filtro a travs del bloque filter con sus bloques filter-name y filter-class. Y
configuramos qu componentes web filtra mediante el bloque filter-mapping con sus
bloques filter-name y url-pattern.
Por ejemplo:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<servlet>
<servletname>DataSourceServlet</servletname>
<servletclass>es.aulamentor.DataSourceServlet</servletclass>
</servlet>
<servletmapping>
<servletname>DataSourceServlet</servletname>
<urlpattern>/DataSourceServlet</urlpattern>
</servletmapping>
<filter>
<filtername>AuditoriaFilter</filtername>
<filterclass>es.aulamentor.AuditoriaFilter</filterclass>
</filter>
<filtermapping>
<filtername>AuditoriaFilter</filtername>
<urlpattern>/*</urlpattern>
</filtermapping>
</webapp>
En este ejemplo, adems de un Java Servlet de un ejemplo anterior, tenemos un Filtro que se
llama AuditoriaFilter implementado mediante la clase es.aulamentor.AuditoriaFilter que filtra (es
decir, intercepta las peticiones) cualquier componente web de la aplicacin.
A travs del patrn de URL, podramos afinar un poco ms el filtrado. Por ejemplo, si
queremos que solo filtre los ficheros HTML, podramos poner *.html en vez de /*, o
/RequestServlet si lo que queremos es filtrar a ese Java Servlet o JavaServer Page concreta.
Hay muchas posibilidades.
176
importjava.io.IOException;
importjava.util.Calendar;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
publicclassAuditoriaFilterimplementsFilter
{
publicvoidinit(FilterConfigfConfig)throwsServletException
{
}
publicvoiddoFilter(ServletRequestrequest,ServletResponse
response,FilterChainchain)throwsIOException,ServletException
{
Calendartime=Calendar.getInstance();
System.out.println("AccesodesdeIP:"+request.getRemoteAddr()+
"alas"+time.get(Calendar.HOUR)+":"++
time.get(Calendar.MINUTE));
chain.doFilter(request,response);
System.out.println("Contestadoalas"+time.get(Calendar.HOUR)+
":"++time.get(Calendar.MINUTE));
}
publicvoiddestroy()
{
}
}
Es muy importante siempre realizar la llamada al siguiente miembro de la cadena (que puede
ser otro filtro o el componente web final) mediante el mtodo doFilter() del parmetro
FilterChain. Aunque tambin existe la posibilidad de desviar la ejecucin, invocando a otro
componente web (por ejemplo de error) a travs del RequestDispatcher como ya sabemos
hacer. Es decir, que un filtro puede decidir en un momento dado interrumpir la ejecucin
normal de la peticin y desviarla por el motivo que sea a otro componente.
La ejecucin en el entorno de desarrollo debera mostrar algo as:
177
Como mencionamos, desde Java EE 6.0 tambin existe la opcin de obviar el descriptor de
despliegue y utilizar anotaciones Java para las definiciones y configuraciones. En este caso,
usaremos la anotacin @WebFilter con sus atributos filterName y urlPatterns:
packagees.aulamentor;
importjava.io.IOException;
importjava.util.Calendar;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.annotation.WebFilter;
@WebFilter(filterName="AuditoriaFilter",urlPatterns={"/*"})
publicclassAuditoriaFilterimplementsFilter
{
publicvoidinit(FilterConfigfConfig)throwsServletException
{
}
publicvoiddoFilter(ServletRequestrequest,ServletResponse
178
chain.doFilter(request,response);
System.out.println("Contestadoalas"+time.get(Calendar.HOUR)+
":"++time.get(Calendar.MINUTE));
publicvoiddestroy()
{
}
}
El resultado debera ser el mismo.
En casos de que existiese ms de un filtro, y que adems filtrasen al mismo componente web,
su ejecucin se realizara en el orden en el que fueron definidos.
7.6
El protocolo HTTP es un protocolo sin estado, es decir, cada peticin que se recibe en el
servidor de un mismo cliente se recibe como si fuese la primera peticin que hace. Es decir,
no hay constancia de que ya se hubiese conectado antes y hubiera solicitado una accin.
Este es un inconveniente importante. Supone por ejemplo, que aunque un cliente ya se
hubiera autenticado con el sistema, como la prxima peticin parece una peticin nueva
pedira autenticarse de nuevo. O que un cliente que mediante una peticin anterior movi un
producto al carrito de la compra en una aplicacin de comercio electrnico, en la siguiente
peticin el carrito aparece vaco.
Por suerte, el protocolo HTTP contempla la posibilidad de almacenar en el lado cliente
informacin del servidor, de manera que dicha informacin viaje a partir de entonces en cada
nueva peticin, y tanto la aplicacin Web como el Servidor de Aplicaciones Java EE puedan
usarla para recordar al cliente.
Esta informacin que se puede almacenar en el lado cliente recibe el nombre de Cookie.
7.6.1 Cookies
Bsicamente, una Cookie es una pareja formada por una clave y un valor que contiene
informacin textual. Es decir, tiene un nombre que identifica la Cookie y un valor asociado,
junto con alguna informacin relacionada adicional que ahora comentaremos sobre cundo
caduca, quin la cre, quin la puede ver, etc
179
El hecho de que se puedan crear desde el servidor, es decir, desde una aplicacin web, las
hace muy tiles para poder recordar los clientes y evitar interacciones redundantes,
prdidas de informacin y similares.
Normalmente (a no ser que tengamos el navegador configurado para evitarlas) en nuestro
navegador tendremos decenas de Cookies guardadas sin que furamos conscientes de ello.
Por ejemplo, si utilizas Mozilla Firefox ves a la opcin de men Firefox -> Options ->
Options:
En la opcin Privacy, selecciona Use custom settings for history en la seccin history,
y entonces pulsa el botn Show Cookies:
180
Te sorprender ver todas las que tienes (incluyendo Cookies de Aula Mentor):
181
En el caso de Internet Explorer, es un poco ms complicado. Ir a la opcin de men tools > Internet Options:
182
183
Se abrir el explorador de archivos, y tendremos que buscar todos aquellos que empiezan
por Cookie:
184
Bien, veamos qu informacin guarda una Cookie antes de meternos con el API Java para
crearlas y acceder a ellas desde nuestras aplicaciones:
Cookies
ya
existentes
son
accesibles
travs
de
la
peticin
las
nuevas,
una
vez
creadas
se
deben
incluir
en
la
respuesta
Cookie[]cookies=request.getCookies();
if(cookies!=null)
for(inti=0;i<cookies.length;i++)
if(cookies[i].getName().equals("CONTADOR"))
cookie=cookies[i];
break;
if(cookie==null)
cookie=newCookie("CONTADOR","0");
intcont=Integer.parseInt(cookie.getValue());
cookie.setValue(Integer.toString(cont+1));
cookie.setMaxAge(604800);//Unasemanaensegundos.
186
response.addCookie(cookie);
%>
Nmerodevecesvisitadaestapgina:<%=cookie.getValue()%>
</BODY>
</HTML>
Al ejecutar la aplicacin desde un navegador y recargar (o refrescar) la pgina varias veces,
veremos que el contador sigue contando donde se qued. Es mas, si paramos el servidor y
cerramos el navegador y volvemos a rearrancar todo, el contador debera seguir por donde
iba tambin. Sin embargo, si utilizamos otro navegador distinto o el mismo pero desde otra
mquina de nuestra red, veremos que el contador comienza en cero porque ese navegador
no tiene la Cookie guardada.
Y si le pedimos al navegador que nos muestre todas las Cookies que tiene (filtramos por
CONTADOR) veremos todos los datos de nuestra Cookie.
187
Normalmente
dicha
Cookie
se
llama
JSESSIONID
es
gestionada
Devuelve una coleccin con el nombre de todos los atributos que contiene.
void setAttribute(java.lang.String name, java.lang.Object value);
Guarda un atributo con su valor.
void removeAttribute(java.lang.String name);
Elimina un atributo.
void invalidate();
Elimina la sesin del servidor. Recordemos que su creacin no se realiza a travs de
un constructor sino simplemente pidindosela a la peticin HTTP.
Los Servidores de Aplicacin Java EE, implementan un sistema de expiracin de sesiones
inactivas. El motivo es que la sesin consume recursos y no se puede garantizar ni que la
aplicacin web implemente un sistema de limpieza (invocando el mtodo invalidate() cuando
un usuario termine de trabajar con la aplicacin), ni que el usuario de las aplicacin web
siempre termine de manera ordenada la aplicacin invocando la peticin de limpieza (por
ejemplo, un logout) en vez de cerrar el navegador directamente. Sin este sistema de
expiracin, podramos terminar con infinitas sesiones hurfanas en el servidor.
Este tiempo de expiracin, es un parmetro de configuracin propio de cada servidor. En el
caso de Apache Tomcat 7.0.x se realiza en el fichero de configuracin /conf/web.xml que
por defecto viene con media hora de tiempo:
<sessionconfig>
<sessiontimeout>30</sessiontimeout>
</sessionconfig>
Todos los objetos que se guarden en la sesin, deben ser serializables (es decir,
implementar java.io.Serializable). El motivo es que los Servidores de Aplicacin Java EE,
normalmente implementan mecanismos de persistencia de las sesiones para facilitar
mecanismos de balanceo de carga y tolerancia a fallos, para liberar recursos de memoria,
etc.. y si el contenido no es serializable no lo puede guardar.
Como buena prctica, la informacin guardada en la Sesin HTTP debe de ser lo ms
pequea posible.
Veamos un ejemplo similar al que mostramos con las Cookies, pero en esta ocasin aade
un botn para invalidar la sesin y comprobar como se pierde la informacin del contador y
comienza de nuevo en uno.
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>Contador</TITLE>
190
if(request.getParameter("invalidate")!=null&&
request.getParameter("invalidate").equals("true"))
{
sesion.invalidate();
isInvalidate=true;
}
else
{
if(sesion.getAttribute("CONTADOR")!=null)
{
cont=
((Integer)sesion.getAttribute("CONTADOR")).intValue();
}
sesion.setAttribute("CONTADOR",newInteger(cont+1));
}
%>
<FORMmethod="POST"action="/EjemplosWeb/sesion.jsp">
<TABLEborder="0">
<%
if(!isInvalidate)
{
%>
<TR>
<TD>Nmerodevecesvisitadaestapgina:<%=cont%></TD>
</TR>
<%
}
%>
<TR>
<TD>Invalidarsesin:<INPUTtype="checkbox"
name="invalidate"value="true"></TD>
</TR>
<TR>
<TD><INPUTtype="submit"value="Refrescar"></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
Al ejecutar el ejemplo desde un navegador externo, deberamos ver algo as:
191
Y si le pedimos al navegador que nos muestre todas las Cookies que tiene (filtramos por
localhost) veremos la Cookie JSESSIONID que el Servidor de Aplicaciones Java EE ha
creado para gestionar la Sesin HTTP.
7.7
Gestin de eventos
Las especificaciones Java EE definen una serie de notificacin de eventos a los que las
aplicaciones web se pueden suscribir para ser notificadas de cundo dichos eventos ocurren.
El funcionamiento de la gestin de eventos en las aplicaciones web funciona igual que en las
aplicaciones visuales de escritorio (AWT/Swing). Es decir, siguen ms o menos el siguiente
diagrama:
193
Bsicamente, contamos con dos piezas fundamentales. Un notificador (Notifier), que es quin
generar los eventos, y un escuchador (Listener) que es quien est interesado en dichos
eventos para reaccionar y actuar en consecuencia.
Para que un escuchador, pueda escuchar los eventos de un notificador, ha de subscribirse a
estos. En caso de estar subscrito, el notificador, cuando ocurra el evento, se lo notificar al
escuchador. En Java, esto significa enviar un mensaje concreto al escuchador (ejecutar un
mtodo concreto).
El mecanismo que tenemos en Java de poder garantizar que el escuchador implementa dichos
mtodos, es forzndole a implementar un interfaz. Y esto lo consigue mediante el API del
mtodo de subscripcin, que solo permite recibir parmetros de un tipo concreto. Luego el
escuchador interesado ha de ser de dicho tipo para poder subscribirse.
Un escuchador, igual que se subscribe, puede finalizar la subscripcin.
Los notificadores pasan la informacin a los escuchadores invocando un mtodo concreto
como ya hemos comentado, pasndole como parmetro un evento que encapsula toda la
informacin necesaria para conocer lo que ha ocurrido.
Los eventos contienen informacin sobre lo que ha ocurrido, accesible a travs de distintos
mtodos.
Ahora bien, existe una diferencia muy importante de operativa con las aplicaciones Java SE
(visuales de escritorio), y es que en Java EE no hay que invocar un mtodo para suscribirse
una familia de eventos (addXXXListener), sino que basta con:
194
javax.servlet.ServletContextAttributeEvent
javax.servlet.http.HttpSessionEvent
javax.servlet.http.HttpSessionBindingEvent
javax.servlet.ServletRequestEvent
javax.servlet.ServletRequestAttributeEvent
A continuacin aadiremos una tabla con un listado de todos los interfaces que hay para cada
una de las familias de eventos que hemos visto, y sus mtodos:
javax.servlet.ServletContextListener
contextDestroyed
contextInitialized
attributeAdded
javax.servlet.ServletContextAttribute
attributeRemoved
attributeReplaced
javax.servlet.http.HttpSessionActivationListener
javax.servlet.http.HttpSessionBindingListener
sessionDidActivate
sessionWillPassivate
valueBound
valueUnbound
195
attributeAdded
javax.servlet.http.HttpSessionAttributeListener
attributeRemoved
attributeReplaced
javax.servlet.ServletRequestListener
requestDestroyed
requestInitialized
attributeAdded
javax.servlet.ServletRequestAttributeListener
attributeRemoved
attributeReplaced
No nos detendremos en explicar uno a uno cada mtodo. El API Java EE esta disponible en la
web, as que no lo reproduciremos por completo aqu.
Veamos eso si, cmo se suscribe una clase a un notificador mediante el descriptor de
despliegue y mediante anotaciones Java:
Mediante anotaciones Java (recordemos que esta opcin solo est disponible desde
Java EE 6.0). Utilizaremos la anotacin @Weblistener
importjavax.servlet.annotation.WebListener;
@WebListener
publicclassEjemploListenerimplements
Y la clase es.aulamentor.EjemploListener ya implementar los interfaces necesarios
para las acciones que quiera escuchar.
Veamos un ejemplo que escucha todos los eventos posibles, y muestra por consola una lnea
por cada evento que ha ocurrido. Lo ejecutaremos junto con la aplicacin que demostraba el
uso de la Sesin HTTP para ver qu eventos se van lanzando:
packagees.aulamentor;
importjavax.servlet.ServletContextAttributeEvent;
importjavax.servlet.ServletContextAttributeListener;
importjavax.servlet.ServletContextEvent;
importjavax.servlet.ServletContextListener;
importjavax.servlet.ServletRequestAttributeEvent;
importjavax.servlet.ServletRequestAttributeListener;
importjavax.servlet.ServletRequestEvent;
196
@WebListener
publicclassEjemploListenerimplementsServletContextListener,
ServletContextAttributeListener,HttpSessionListener,
HttpSessionAttributeListener,HttpSessionActivationListener,
HttpSessionBindingListener,ServletRequestListener,
ServletRequestAttributeListener
{
publicvoidrequestDestroyed(ServletRequestEventev)
{
System.out.println("SehainvocadorequestDestroyed...");
}
publicvoidattributeAdded(HttpSessionBindingEventev)
{
System.out.println("SehainvocadoattributeAdded...");
}
publicvoidcontextInitialized(ServletContextEventev)
{
System.out.println("SehainvocadocontextInitialized...");
}
publicvoidsessionDidActivate(HttpSessionEventev)
{
System.out.println("SehainvocadosessionDidActivate...");
}
publicvoidvalueBound(HttpSessionBindingEventev)
{
System.out.println("SehainvocadovalueBound...");
}
publicvoidattributeAdded(ServletContextAttributeEventev)
{
System.out.println("SehainvocadoattributeAdded...");
}
publicvoidattributeRemoved(ServletContextAttributeEventev)
{
System.out.println("SehainvocadoattributeRemoved...");
}
publicvoidsessionDestroyed(HttpSessionEventev)
{
System.out.println("SehainvocadosessionDestroyed...");
}
publicvoidattributeRemoved(HttpSessionBindingEventev)
{
System.out.println("SehainvocadoattributeRemoved...");
}
197
publicvoidattributeAdded(ServletRequestAttributeEventev)
{
System.out.println("SehainvocadoattributeAdded...");
}
publicvoidvalueUnbound(HttpSessionBindingEventev)
{
System.out.println("SehainvocadovalueUnbound...");
}
publicvoidsessionWillPassivate(HttpSessionEventev)
{
System.out.println("SehainvocadosessionWillPassivate...");
}
publicvoidsessionCreated(HttpSessionEventev)
{
System.out.println("SehainvocadosessionCreated...");
}
publicvoidattributeReplaced(HttpSessionBindingEventev)
{
System.out.println("SehainvocadoattributeReplaced...");
}
publicvoidattributeReplaced(ServletContextAttributeEventev)
{
System.out.println("SehainvocadoattributeReplaced...");
}
publicvoidattributeRemoved(ServletRequestAttributeEventev)
{
System.out.println("SehainvocadoattributeRemoved...");
}
publicvoidcontextDestroyed(ServletContextEventev)
{
System.out.println("SehainvocadocontextDestroyed...");
}
publicvoidattributeReplaced(ServletRequestAttributeEventev)
{
System.out.println("SehainvocadoattributeReplaced...");
}
publicvoidrequestInitialized(ServletRequestEventev)
{
System.out.println("SehainvocadorequestInitialized...");
}
}
La ejecucin en el entorno de desarrollo debera mostrar algo as:
198
199
200
PARA RECORDAR
Java
EE.
El
mtodo
utilizado
es
el
getConnection
de
javax.sql.DataSource
Los filtros son unos componentes que se despliegan como parte de la aplicacin
Web, y cuya misin es interceptar las peticiones y respuesta de un componente
concreto para por ejemplo, realizar algn tipo de validacin, algn tipo de auditoria,
algn tipo de transformacin, etc
init: Se invoca una nica vez en la vida del filtro y se utiliza para realizar las
labores de inicializacin.
destroy: Se invoca una nica vez en la vida del filtro y se utiliza para realizar las
labores de limpieza y liberacin de recursos si fuese necesario.
201
Las especificaciones Java EE definen una serie de notificacin de eventos a los que
las aplicaciones web se pueden suscribir para ser notificadas de cundo dichos
eventos ocurren. Contamos con dos piezas fundamentales:
Un notificador (Notifier), que es quin generar los eventos
Un escuchador (Listener) que es quien est interesado en dichos eventos para
reaccionar y actuar en consecuencia.
202
Unidad de Aprendizaje 8
JAVASERVER PAGES
AVANZADO
NDICE
8.1
8.2
8.3
8.4
8.5
8.1
Introduccin
8.2
Las etiquetas JSP estndar, son etiquetas del estilo de las empleadas en las pginas HTML o
en los descriptores de despliegue (XML) que permiten realizar acciones en el momento de
ejecucin de la pgina.
Cualquier etiqueta JSP podra ser sustituida sin ningn problema por cdigo Java equivalente
como ya hicimos en unidades anteriores.
La sintaxis de una etiqueta JSP consiste en el prefijo jsp: seguido del identificador de la
accin y opcionalmente atributos (parejas de nombre y valor).
Las especificaciones definen mltiples etiquetas JSP estndar, a saber:
<jsp:include>: incluye el resultado de otra pgina JSP, Java Servlet u otro componente
web esttico.
<jsp:body>: identifica el comienzo del cuerpo del documento HTML (viene a sustituir a
<BODY>). Se ha de utilizar siempre que en la pgina se utilice la accin
<jsp:attribute>.
Son muchas las etiquetas pero trataremos solo algunas de ellas porque en general, a
excepcin de unas pocas, su uso es muy raro.
La etiqueta <jsp:include> produce un efecto exactamente igual que el de la directiva <%@
include file=xxx %> que ya hemos visto y practicado en alguna actividad durante el curso.
La diferencia es que el atributo que necesita se llama page.
Algunos ejemplos:
<jsp:includepage="copyright.html"/>
<jsp:includepage="/index.html"/>
<jsp:includepage="/login.jsp">
<jsp:paramname="usuario"value="pepe"/>
</jsp:include>
Y la etiqueta <jsp:forward> es parecida a <jsp:include> con la diferencia de que no incluye el
resultado, sino que delega en ese nuevo recurso la respuesta.
Algunos ejemplos:
<jsp:forwardpage="/servlet/login"/>
<jsp:forwardpage="/servlet/login">
<jsp:paramname="usuario"value="pepe"/>
</jsp:forward>
Otra etiqueta tpica es la de referenciar o instanciar una clase Java para trabajar con ella.
Como vimos en la enumeracin de etiquetas existentes, la etiqueta a emplear es
<jsp:useBean>. Esta etiqueta busca un objeto con el identificador dado en el mbito
seleccionado y de no encontrarlo, lo crea con dicho identificador en dicho mbito.
Utiliza por tanto estos tres atributos:
206
request: la peticin.
page: la pgina:
application: la aplicacin.
Por ejemplo:
<jsp:useBeanid="cesta"scope="session"class="edu.aulamentor.Cesta"/>
Esta etiqueta busca en la sesin HTTP un objeto de la clase edu.aulamentor.Cesta que se
llama cesta. Si no existiera lo crea.
Y esto para qu? Pues normalmente va a acompaado de las etiquetas <jsp:setProperty> y
<jsp:getProperty> para utilizar el objeto en cuestin.
<jsp:setProperty> nos permite establecer el valor de alguno de los atributos del objeto. Para
ello utiliza tres atributos:
Por ejemplo:
<jsp:useBeanid="cesta"scope="session"class="edu.aulamentor.Cesta"/>
<jsp:setPropertyname="cesta"property="total"value="0.0"/>
De igual forma, podemos acceder al valor de un atributo del objeto mediante la accin
<jsp:getAttribute>. Para ello utiliza dos atributos:
Por ejemplo:
Totaldelacestaes:<jsp:getPropertyname="cesta"property="total"/>
Para que estas etiquetas funcionen bien, la clase Java debe seguir las especificaciones
JavaBean. Esto significa que, entre otras cosas, la clase debe tener un constructor por defecto
(constructor sin parmetros) y un getter/setter por cada atributo (siguiendo la norma de utilizar
get y set seguido del nombre del atributo con la primera letra en maysculas). Es decir, en
nuestro ejemplo:
packagees.aulamentor;
publicclassCesta
{
privatedoubletotal;
publicCesta()
{
}
207
publicdoublegetTotal()
{
returnthis.total;
}
publicvoidsetTotal(doubleparam)
{
this.total=param;
}
}
Simplemente por comparar, este mismo ejemplo pero con cdigo Java habra sido algo as:
<%
es.aulamentor.Cestacesta=
(es.aulamentor.Cesta)session.getAttribute(cesta);
cesta.setTotal(0.0);
%>
Totaldelacestaes:<%=cesta.getTotal()%>
Pero la etiqueta <jsp:setProperty> puede tener un uso ms potente todava, y es el de
transferir el valor de los parmetros de un formulario que se reciba en una peticin a los
atributos de un objeto Java sin necesidad de ir uno a uno. Basta con eliminar el atributo value:
<jsp:useBeanid="cesta"scope="session"class="es.aulamentor.Cesta"/>
<jsp:setPropertyname="cesta"property="*"/>
En este caso, el servidor va a buscar todos (porque hemos usado el carcter * en vez de un
nombre concreto) aquellos parmetros que vengan en la peticin que se llamen igual que
algn atributo de la clase Cesta y ponerle su valor.
8.3
208
Todos los objetos implcitos son una coleccin del tipo Map, es decir, contiene parejas de
clave y valor. Estos son los que hay:
Por tanto, si queremos referenciar al atributo persona que est en la Sesin HTTP tenemos
dos opciones:
${persona}
o para evitar colisiones en el caso de que existiese otro atributo con el mismo nombre en
mbitos con mayor precedencia:
209
${sessionScope.persona}
Ahora, si queremos seguir profundizando en el atributo, accediendo a otros atributos ms
internos en su estructura (como el ejemplo anterior donde accedimos al nombre del perro de la
persona), es cuando utilizaremos una secuencia de nombres de atributos separados por
puntos:
${sessionScope.persona.perro.nombre}
Ahora bien, llegados a este punto es importante volver a recordar, que esto solo funciona si las
clases Java accedidas siguen las especificaciones JavaBean, que entre otras cosas obligan a
que:
La clase tenga un mtodo getter por cada atributo siguiendo la regla de que se llamara
get seguido del nombre del atributo con la primera letra en mayscula.
La clase tenga un mtodo setter por cada atributo siguiendo la regla de que se llamara
set seguido del nombre del atributo con la primera letra en mayscula.
210
Lo
mismo
que
el
punto,
es
decir,
${perro.nombre}
es
equivalente
Para profundizar en atributos que son de algn tipo de coleccin (array, Map o List),
por ejemplo: ${perros[3].nombre}
Las expresiones EL tambin permiten implementar una mnima lgica, aunque no est
recomendado su uso para ello. Soporta los operadores aritmticos (+, -, *, / y %), los
operadores lgicos (&&, || y !) y los operadores relacionales (==, =, <, >, <= y >=).
Otro dato a tener muy en cuenta es que las expresiones EL pueden ser usadas como valores
de los atributos de las etiquetas JSP que ya hemos comentado en la seccin anterior y en las
que comentaremos a continuacin.
8.4
Al igual que existen las etiquetas JSP estndar definidas en las especificaciones JSP, con el
tiempo surgi otra especificacin denominada JSTL (JavaServer Page Standard Tag Library o
Librera de etiquetas JSP estndar) que aglutina una serie de libreras de etiquetas o acciones
adicionales que persiguen el mismo objetivo que las anteriores: facilitar la programacin de la
presentacin de las aplicaciones web a diseadores grficos sin conocimientos del lenguaje
Java mediante herramientas visuales orientadas al manejo de etiquetas.
En este curso no pretendemos cubrir todas y cada una de las etiquetas, pero si comentar
cmo se especifica el uso de una librera, qu libreras hay, y algn ejemplo.
La gua de referencia completa de JSTL est disponible en:
http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
Actualmente existen cinco libreras de etiquetas presentes en cualquier servidor de
aplicaciones Java EE completo:
I18N
(en
castellano
internacionalizacin):
Su
prefijo
es
fmt
su
URI
Database
(en
castellano,
Base
de
Datos):
Su
prefijo
es
sql
su
URI
211
Functions
(en
castellano
funciones):
Su
prefijo
es
fn
su
URI
http://search.maven.org/remotecontent?filepath=javax/servlet/jsp/jstl/javax.servlet.jsp.j
stl-api/1.2.1/javax.servlet.jsp.jstl-api-1.2.1.jar
http://search.maven.org/remotecontent?filepath=org/glassfish/web/javax.servlet.jsp.jst
l/1.2.1/javax.servlet.jsp.jstl-1.2.1.jar
212
Una vez hemos copiado ambos dos ficheros en el directorio /WebContent/WEB-INF/lib del
proyecto, si no se fuese el error forzamos una recompilacin mediante la opcin de men:
Project -> Clean:
Revisemos a continuacin brevemente las etiquetas de cada una de las libreras estndar.
Como ya comentamos, no va a ser una explicacin exhaustiva. Simplemente pretendemos
que se conozcan qu posibilidades hay y dnde poder consultar en caso de llegar a
necesitarse alguna.
213
8.4.1 Core
Implementa acciones bsicas para el tratamiento de variables, control de flujo, gestin de
URLs, y otras:
Gestin de variables:
o set: estable el valor de una variable EL o del atributo de una variable EL en uno
de los mbitos posibles. Si dicha variable no existiese la crea.
<c:setvar="titulo"scope="session"value="${param.titulo}"/>
o remove: elimina una variable EL.
<c:removevar="cart"scope="session"/>
Control de flujo:
o choose junto con when y otherwise: viene a ser una especie de estructura
switch, case, default de Java. Evala las condiciones EL de cada etiqueta
when y entra por la que sea true. Si ninguna fuese true, ejecuta la otherwise.
<c:choose>
<c:whentest="${cont==0}">
Nosehaencontradoningnelemento.
</c:when>
<c:otherwise>
Sehanencontrado${cont}elementos.
</c:otherwise>
</c:choose>
o forEach: permite iterar por una coleccin de elementos.
<c:forEachvar="libro"items="${sessionScope.cesta.libros}">
<TR>
<TDalign="right"bgcolor="#ffffff">
${libro.titulo}
</TD>
</TR>
</c:forEach>
o forTokens: permite iterar por una coleccin de tokens separados por un
delimitador.
o if: evala una condicin EL y si es true sigue ejecutando el contenido del
bloque.
<c:iftest="${param.nombre==Pepe}">
<H1>ElnombreesPepe.</H1>
</c:if>
Gestin de URLs:
o import: importa el contenido de un recurso de Internet en una variable EL.
Puede utilizar param para especificar parmetros.
<c:importurl="/introduccion.txt"var="texto"/>
o redirect: enva al cliente un cdigo HTTP de redireccin. Puede utilizar param
para especificar parmetros.
214
8.4.2 XML
Implementa acciones bsicas para el parseo de documentos XML, control de flujo
recorriendo estructuras XML y transformaciones:
Parseo:
o out: evala una expresin XPath y su resultado lo devuelve como parte de la
respuesta.
o parse: parsea un documento XMl y guarda el contenido en una variable
identificada mediante EL.
o set: evala una expresin XPath y su resultado lo guarda en una variable
identificada mediante EL.
Control de flujo:
o choose junto con when y otherwise: similar a la librera Core pero itera sobre el
resultado de evaluar una expresin XPath sobre un documento XML.
o forEach: similar a la librera Core pero itera sobre el resultado de evaluar una
expresin XPath sobre un documento XML.
o if: similar a la librera Core pero itera sobre el resultado de evaluar una
expresin XPath sobre un documento XML.
Transformacin:
o transform: aplica una transformacin a un documento XML especificado en el
atributo doc definida en una plantilla XSLT especificada en el atributo xslt.
Ms detalles y ejemplos:
http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
8.4.3 I18N
Implementa acciones bsicas para la gestin de la localizacin, seleccionar los mensajes a
mostrar en base a dicha localizacin y el formateo de nmeros y fechas:
Localizacin:
o setLocale: fuerza una localizacin concreta independientemente de la que
enviara el cliente web.
o requestEncoding: especifica la codificacin a utilizar para interpretar los
parmetros de una peticin.
Mensajes:
215
8.4.4 Database
Implementa acciones bsicas para el acceso a las Bases de Datos:
Configuracin:
o setDataSource: sirve para especificar el identificador JNDI del Data Source a
utilizar.
<sql:setDataSourcedataSource="jdbc/TestDB"/>
SQL:
o query: ejecuta una query que devuelve un resultado que guarda en el atributo
var. Dicho resultado es un Java Bean con los siguientes atributos (a tener en
cuenta para poder explotar la informacin resultante mediante EL):
public String[] columnNames
public int rowCount
public Map[] rows()
public Object[][] rowsByIndex
public boolean limitedByMaxRows
Un ejemplo imaginando que tenemos una tabla LIBROS con columnas como
AUTOR, TITULO y PAGINAS:
<sql:queryvar="libros"sql="select*fromLIBROSwhereAUTOR=
?">
<sql:paramvalue="${autor}"/>
</sql:query>
<c:forEachvar="libro"begin="0"items="${libros.rows}">
<H2>${libro.titulo}</H2><BR>
Nm.DePginas:${libro.paginas}<BR><BR>
</c:forEach>
216
8.4.5 Functions
Implementa acciones bsicas de manejo de cadenas de caracteres pero al contrario que
todas las libreras anteriores, ests no son etiquetas como tal sino funciones a emplear en
una EL:
trim: devuelve la cadena sin espacios en blanco por delante ni por detrs.
Ms detalles y ejemplos:
http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
217
8.5
Al igual que existen las libreras de etiquetas JSP estndar estudiadas en la seccin anterior,
las especificaciones Java EE contemplan la posibilidad de que podamos definir e implementar
nuestra propia librera de etiquetas. De esta forma, en caso de haber decidido minimizar el
cdigo Java que aparecer en las pginas JSP podemos implementar etiquetas que cubran
necesidades particulares de nuestra aplicacin.
De igual forma, encontraremos en Internet cantidad de libreras adicionales de etiquetas
desarrolladas por terceras personas.
El API necesario para la implementacin de etiquetas personalizadas se encuentra en el
paquete: javax.servlet.jsp.tagext;
La implementacin de una etiqueta personalizada siempre ha de implementar el interface:
javax.servlet.jsp.tagext.Tag
o extender la clase:
javax.servlet.jsp.tagext.TagSupport
que es una clase que contiene implementaciones por defecto de los mtodos del interface
Tag.
El interface Tag tiene varios mtodos, pero aqu solo comentaremos:
218
importjava.io.IOException;
importjava.io.Writer;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.tagext.Tag;
importjavax.servlet.jsp.tagext.TagSupport;
publicclassRepiteTagextendsTagSupport
{
privatecharcaracter;
privateintveces;
publicvoidsetCaracter(charcarcater)
{
this.caracter=carcater;
}
publicvoidsetVeces(intveces)
{
this.veces=veces;
}
publicintdoStartTag()throwsJspException
{
219
Writerout=pageContext.getOut();
for(inti=0;i<veces;i++)
{
try
{
out.write(caracter);
}
catch(IOExceptionex)
{
ex.printStackTrace();
}
}
returnTag.EVAL_BODY_INCLUDE;
}
publicintdoEndTag()throwsJspException
{
Writerout=pageContext.getOut();
for(inti=0;i<veces;i++)
{
try
{
out.write(caracter);
}
catch(IOExceptionex)
{
ex.printStackTrace();
}
}
returnTag.EVAL_PAGE;
}
}
A continuacin, necesitamos crear un fichero de configuracin XML donde se le indica al
Servidor Java EE la existencia de una librera personalizada y los detalles. Este fichero de
extensin *.tld debe formar parte de la aplicacin web y su ubicacin es un directorio tlds en
/WEB-INF
En nuestro caso lo llamamos AulaMentorTagLib.tld:
220
Este fichero, sigue una sintaxis concreta. Veamos el contenido para nuestro ejemplo y
repasaremos las etiquetas ms relevantes:
<?xmlversion="1.0"encoding="UTF8"?>
<taglibversion="2.1"xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webjsptaglibrary_2_1.xsd">
<tlibversion>1.0</tlibversion>
<shortname>Aula_Mentor_Tag_Library</shortname>
<uri>http://www.aulamentor.es/jsp/jstl/tags</uri>
<tag>
<name>repite</name>
<tagclass>es.aulamentor.RepiteTag</tagclass>
<bodycontent>scriptless</bodycontent>
<attribute>
<name>caracter</name>
<required>true</required>
</attribute>
<attribute>
<name>veces</name>
<required>false</required>
</attribute>
</tag>
</taglib>
La primera lnea indica que se trata de un archivo XML.
La segunda indica que se trata de la definicin de una librera de etiquetas.
Como bloques o etiquetas relevantes tenemos:
uri: a la que luego haremos referencia desde la pgina JSP para indicar que usamos
esta librera.
221
Por ltimo, ya solo nos queda utilizar la nueva etiqueta en la aplicacin. Para ello vamos a
crear una pgina JSP muy sencilla:
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
<%@tagliburi="http://www.aulamentor.es/jsp/jstl/tags"prefix="am"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>PruebadeTagPersonalizada</TITLE>
</HEAD>
<BODY>
<am:repitecaracter="*"veces="5">
PRUEBA
</am:repite>
<BODY>
</HTML>
Primero, fijmonos en cmo decimos que vamos a utilizar etiquetas de la nueva librera:
<%@tagliburi="http://www.aulamentor.es/jsp/jstl/tags"prefix="am"%>
La URI debe coincidir exactamente con la que especificamos en le fichero de configuracin de
la librera. Y el prefijo, puede ser cualquiera. En este caso hemos decidido que sea: am.
Ahora, veamos dnde y cmo hemos usado la etiqueta:
<am:repitecaracter="*"veces="5">
PRUEBA
</am:repite>
Identificada con el prefijo y utilizando exactamente el mismo nombre que usamos en el fichero
de configuracin. Hemos usado tambin sus dos atributos (solo carcter era obligatorio).
222
223
PARA RECORDAR
Las etiquetas JSP estndar, son etiquetas del estilo de las empleadas en las
pginas HTML o en los descriptores de despliegue (XML) que permiten realizar
acciones en el momento de ejecucin de la pgina. Su sintaxis consiste en el prefijo
jsp:.
224
Unidad de Aprendizaje 9
NDICE
9.1
9.2
9.3
9.4
9.1 Introduccin
Esta es la ltima unidad del curso. En ella trataremos algunos temas no menos importantes
que no han tenido cabida en las unidades anteriores como son la gestin de errores y la
seguridad en Java EE.
Por ltimo, daremos una breve pincelada de algunos frameworks de desarrollo de aplicaciones
web, que construidos sobre los conceptos que hemos visto en este curso pretenden acelerar y
facilitar el desarrollo de aplicaciones web. La idea es simplemente que el alumno conozca de
su existencia y profundice en alguno de ellos si los encuentra de inters. Cada uno de ellos por
si solo, dara lugar a un curso completo.
9.2
Gestin de errores
Segn las especificaciones Java EE, existen dos alternativas no excluyentes para la gestin de
errores:
Evidentemente cada una tiene sus ventajas e inconvenientes. Por un lado, la programtica es
la gestin ms potente y flexible, sin embargo el cdigo es ms complejo y la lgica ms
complicada de seguir. Por otro lado, la declarativa es la gestin ms sencilla pero por otro
lado tiene ms restricciones.
La gestin programtica ya la conocemos. Mediante las estructura try & catch o cualquier otro
medio de deteccin de errores, realizamos mediante cdigo redirecciones a pginas concretas
de tratamiento y muestra del error. Por tanto, en esta unidad nos vamos a ceir a la gestin
declarativa.
Mediante la gestin declarativa podemos controlar dos aspectos:
Por ejemplo, la pgina por defecto para un error 404 (recurso no encontrado) de
Apache Tomcat 7.0.x es la siguiente:
227
Sin embargo, mediante los bloques error-page y sus bloques error-code (para
especificar el cdigo de error) y location (para especificar qu componente web
invocar) podemos cambiar este comportamiento por defecto.
Veamos un ejemplo de cmo cambiar la pgina que se muestra para el error HTTP
404:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"
id="WebApp_ID"version="3.0">
<errorpage>
<errorcode>404</errorcode>
<location>/Error404.jsp</location>
</errorpage>
</webapp>
Y esta es la pgina JSP:
<%@pagelanguage="java"contentType="text/html;charset=ISO
88591"pageEncoding="ISO88591"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;
charset=ISO88591">
<TITLE>Pginanoencontrada.Disculpelas
molestas...</TITLE>
</HEAD>
<BODY>
Pginanoencontrada.Disculpelasmolestas...<BR/>
Sielproblemeapersistepngaseencontactoconel
administrador.<BR/>
<%=Calendar.getInstance().getTime()%>
</BODY>
</HTML>
228
Java
no
esperadas
con
difcil
solucin.
Por
ejemplo,
229
231
9.3
Gestin de la seguridad
Por ejemplo, al acceder a una aplicacin web se nos puede solicitar identificador y
contrasea para validar que somos quien decimos ser. Existen otras opciones adems
del identificador y contrasea, como son los certificados digitales.
Autorizacin: Asegurarse que un cliente accede solo a los recursos a los que
puede/debe tener acceso y no a otros.
Integridad de datos: Asegurarse que los mensajes llegan sin haber sido alterados
por el camino.
Por ejemplo, evitar que alguien pueda estar pinchado a la red y modifique el
contenido de los mensajes que enviamos a un servidor.
Por ejemplo, evitar que alguien pueda estar pinchado a la red y lea informacin
sensible como contraseas, nmeros de cuenta y similares que fluye entre nuestro
navegador y el servidor.
No repudio: Asegurarse que quedan evidencias que eviten que un cliente pueda
negar haber realizado una transaccin contra el servidor.
Por ejemplo, evitar que alguien pueda decir que no hizo algo en nuestro sistema.
Auditoria: Asegurarse que queda registrado todos los eventos relacionados con la
seguridad para posteriores estudios y anlisis.
Cmo encajan estos conceptos juntos y cmo se utilizan para securizar una aplicacin web?
En el Servidor de Aplicaciones Java EE gestionado por los administradores de sistemas
existen definidos usuarios y grupos. Dependiendo del Servidor de Aplicaciones Java EE y de la
solucin corporativa que haya instalada en cada caso, esto usuarios y grupos estarn
definidos directamente en el servidor o estn delegados en el Sistema Operativo, o en un
Servidor de Directorio LDAP. Lo importante en nuestro caso es que ambos dos conceptos son
un tema ajeno a la aplicacin web y est delegado en la infraestructura.
233
Los roles sin embargo, si que son algo que definimos en la aplicacin. Es un concepto
abstracto de quin puede hacer qu. Es decir, en la aplicacin diremos que a un recurso
concreto solo puede acceder el rol A y B. Y a otro recurso distinto solo el rol A o por el
contrario el rol C.
El truco llega en el momento de la instalacin de la aplicacin donde el administrador
encargado de dicho proceso mapear el concepto abstracto de rol, con los conceptos reales
de usuario y/o grupo.
Y el conjunto de esas definiciones para una aplicacin concreta, es lo que llamamos un Realm.
Pero vayamos por partes. Ha quedado claro que primero necesitamos contar con una serie de
usuarios y opcionalmente grupos en nuestro sistema.
En el caso de este curso, estamos usando el Servidor de Aplicaciones Java EE Apache
Tomcat 7.0.x que ofrece distintas alternativas de configuracin. Optaremos por la ms
sencilla, que consiste en el uso de un fichero de configuracin de usuarios: /conf/tomcatusers.xml
La primera dificultad viene porque Apache Tomcat denomina rol lo que en la teora de
seguridad hemos llamado grupo. No pasa nada, pero evidentemente crea confusin. As que
es importante recordarlo a lo largo del resto de esta seccin: lo que en la configuracin de
Apache Tomcat se denomina rol, realmente corresponde al concepto que hemos comentado
de grupo. No tiene nada que ver con el concepto abstracto de rol que aplica a las aplicaciones
web y que veremos mas adelante.
Vamos a trabajar sobre un ejemplo donde tendremos seis usuarios: usuario1, usuario2,
usuario3, usuario4, usuario5 y usuarios6, y tres grupos: clientes (representa usuarios normales
de nuestra aplicacin), operadores (representa usuarios especiales que pertenecen a nuestra
empresa y que tienen ms permisos que los usuarios cliente) y administradores (representa
usuarios nuevamente de nuestra empresa que tienen todos los permisos).
Los dos primeros usuarios pertenecen al primer grupo, los dos siguientes al segundo grupo y
los dos ltimos al tercero. Las contraseas de cada usuario son su propio identificador, es
decir, usuario1 tendr como contrasea usuario1, y as sucesivamente.
Vamos a editar el fichero de configuracin en el entorno de desarrollo Eclipse IDE for Java EE
Developers (recordemos que los ficheros de configuracin de Apache Tomcat en este caso
estarn en un proyecto denominado Servers):
234
como a la de operadores y los administradores a todas. Para ello, el navegador nos pedir un
usuario y una contrasea, para saber quin somos y si nos puede autorizar o no. Pero la
configuracin para que esto ocurra la veremos despus de escribir el cdigo.
Pgina HTML (publica.html):
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>EjemplodeSeguridad</TITLE>
</HEAD>
<BODY>
Estapginaespblicayaccesibleportodoelmundo.
<FORMmethod="POST"action="/EjemplosWeb/clientes.jsp">
<INPUTtype="submit"value="Clientes">
</FORM>
<FORMmethod="POST"action="/EjemplosWeb/operadores.jsp">
<INPUTtype="submit"value="Operadores">
</FORM>
<FORMmethod="POST"action="/EjemplosWeb/administradores.jsp">
<INPUTtype="submit"value="Adminitradores">
</FORM>
</BODY>
</HTML>
Pgina JSP (clientes.jsp):
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<METAhttpequiv="ContentType"content="text/html;charset=ISO
88591">
<TITLE>EjemplodeSeguridad</TITLE>
</HEAD>
<BODY>
PginadeClientesaccesibleporusuarios:
<UL>
<LI>Usuario1</LI>
<LI>Usuario2</LI>
<LI>Usuario3</LI>
<LI>Usuario4</LI>
<LI>Usuario5</LI>
<LI>Usuario6</LI>
</UL>
</BODY>
</HTML>
Pgina JSP (operadores.jsp):
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDHTML4.01Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
236
haya definidos en una empresa De esta manera se consigue una independencia entre la
aplicacin y los sistemas donde se vaya a desplegar.
Es a la hora de instalar la aplicacin, donde se hace un mapeo de roles con usuarios/grupos.
Pero cmo se hace este mapeo es dependiente de cada Servidor de Aplicaciones Java EE.
Cada uno lo realiza en un fichero de configuracin distinto y con una sintaxis distinta. Pero es
ms, en el caso de Apache Tomcat 7.0.x dicho mapeo no existe y nos obliga a que los roles
correspondan con nombres de grupos idnticos lo cual es una restriccin importante.
Las restricciones de acceso a los componentes de la aplicacin web se definen mediante el
bloque security-constraint, el cual a su vez contiene mltiples bloques. Veamos un ejemplo:
<securityconstraint>
<webresourcecollection>
<webresourcename>AreadeOperadores</webresourcename>
<urlpattern>/operadores.jsp</urlpattern>
<httpmethod>GET</httpmethod>
<httpmethod>POST</httpmethod>
</webresourcecollection>
<authconstraint>
<rolename>administradores</rolename>
<rolename>operadores</rolename>
</authconstraint>
<userdataconstraint>
<transportguarantee>NONE</transportguarantee>
</userdataconstraint>
</securityconstraint>
Como se puede observar, primero se define el recurso o conjunto de recursos a proteger,
identificados por una URL que podra usar comodines tipo: /*, o /*.jsp, etc especificando
adems los protocolos HTTP de acceso a tener en consideracin.
Despus de especifican los roles que tienen autorizacin a acceder a los recursos definidos
anteriormente.
Y por ltimo, especifica si las comunicaciones deben ser seguras o no (utilizando HTTPS). Este
bloque puede tomar tres valores:
CONFIDENTIAL: las comunicaciones deben no ser legibles, por tanto se debe usar
HTTPS para acceder a los recursos definidos.
De esta manera, definiramos todas las posibles autorizaciones de acceso a los componentes
de la aplicacin web.
238
BASIC: el servidor pedir al cliente que solicite el usuario y contrasea. Estas viajaran
codificadas en Base64 en claro (a no ser que las comunicaciones sean seguras).
Con todo esto, veamos cmo sera el descriptor de despliegue de nuestro ejemplo:
<?xmlversion="1.0"encoding="UTF8"?>
<webappxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd"id="WebApp_ID"
version="3.0">
<securityrole>
<rolename>clientes</rolename>
</securityrole>
<securityrole>
<rolename>operadores</rolename>
</securityrole>
<securityrole>
<rolename>administradores</rolename>
</securityrole>
<securityconstraint>
<webresourcecollection>
<webresourcename>AreadeAdminitradores</webresourcename>
<urlpattern>/administradores.jsp</urlpattern>
<httpmethod>GET</httpmethod>
<httpmethod>POST</httpmethod>
</webresourcecollection>
<authconstraint>
<rolename>administradores</rolename>
</authconstraint>
<userdataconstraint>
<transportguarantee>NONE</transportguarantee>
</userdataconstraint>
</securityconstraint>
239
<securityconstraint>
<webresourcecollection>
<webresourcename>AreadeOperadores</webresourcename>
<urlpattern>/operadores.jsp</urlpattern>
<httpmethod>GET</httpmethod>
<httpmethod>POST</httpmethod>
</webresourcecollection>
<authconstraint>
<rolename>administradores</rolename>
<rolename>operadores</rolename>
</authconstraint>
<userdataconstraint>
<transportguarantee>NONE</transportguarantee>
</userdataconstraint>
</securityconstraint>
<securityconstraint>
<webresourcecollection>
<webresourcename>AreadeClientes</webresourcename>
<urlpattern>/clientes.jsp</urlpattern>
<httpmethod>GET</httpmethod>
<httpmethod>POST</httpmethod>
</webresourcecollection>
<authconstraint>
<rolename>administradores</rolename>
<rolename>operadores</rolename>
<rolename>clientes</rolename>
</authconstraint>
<userdataconstraint>
<transportguarantee>NONE</transportguarantee>
</userdataconstraint>
</securityconstraint>
<loginconfig>
<authmethod>BASIC</authmethod>
</loginconfig>
</webapp>
Como se puede ver, definimos tres roles, tres colecciones de recursos con sus definiciones de
acceso y el mtodo de autenticacin BASIC.
Si ejecutamos el ejemplo siguiendo la siguiente secuencia lgica:
1. Accedemos a la pgina HTML principal pblica que no est protegida. Deberamos
poder acceder y ver su contenido sin ningn tipo de problema.
240
241
Por lo dems, la pgina puede mostrar la informacin como quiera. Por ejemplo:
<%@pagelanguage="java"contentType="text/html;charset=ISO88591"
pageEncoding="ISO88591"%>
242
<TDcolspan="2">Pginadeejemploparalogin:</TD>
</TR>
<TR>
<TD>Usuario:</td>
<TD><INPUTtype="text"name="j_username"></TD>
</TR>
<TR>
<TD>Contrasea:</td>
<TD><INPUTtype="password"name="j_password"></TD>
</TR>
<TR>
<TDcolspan="2"><INPUTtype="submit"value="Login"></TD>
</TR>
</TABLE>
</FORM>
</BODY>
</HTML>
En esta ocasin, cuando el servidor detecte que ha de pedir autenticacin al cliente, en vez de
solicitar al navegador que muestre una ventana devolver nuestra pgina:
243
9.4
como
la
programacin
transaccional,
la
245
es
un
nuevo
framework
junto
con
Struts
tambin
246
PARA RECORDAR
Autorizacin: Asegurarse que un cliente accede solo a los recursos a los que
puede/debe tener acceso y no a otros.
Integridad de datos: Asegurarse que los mensajes llegan sin haber sido
alterados por el camino.
No repudio: Asegurarse que quedan evidencias que eviten que un cliente pueda
negar haber realizado una transaccin contra el servidor.
Auditoria: Asegurarse que queda registrado todos los eventos relacionados con
la seguridad para posteriores estudios y anlisis.
Las especificaciones Java EE, nos ofrecen dos aproximaciones distintas al tema de
la seguridad:
247
Spring Source naci como una ayuda mas a la programacin web pero con el
tiempo se fue extendiendo a otras muchas reas como la programacin
transaccional, la persistencia de datos, la programacin de batch, para mviles,
etc
248