Manual - Programacion - Java - Tutor Servlets & JSP
Manual - Programacion - Java - Tutor Servlets & JSP
Manual - Programacion - Java - Tutor Servlets & JSP
❍ ¿Qué es JSP?
● Instalación y Configuración
❍ Obtener e Instalar las clases Servlet y JSP
❍ Obtener un Servidor Web Compatible con Servlets o Motor de Servlets
● Primeros Servlets
❍ Estructura Básica de un Servlet
❍ Un Sencillo Servlet que Genera Texto Normal
● Seguimiento de Sesión
❍ Introducción al Seguimiento de Sesión
❍ El API Session Tracking
❍ Ejemplo
Ozito
Servlets y JSP
Introducción
1. ¿Qué son los Servlets Java?
2. ¿Qué Ventajas tienen los Servlets Frente al CGI "Tradicional"?
3. ¿Qué es JSP?
4. ¿Qué Ventajas Tiene JSP?
Ozito
Servlets y JSP
Instalación y Configuración del Servidor
1. Obtener e Instalar los Kits de Desarrollo de Servlets y JSP
2. Instalar un Servidor Web compatible con Servlets
Luego, necesitamos decirle a javac dónde encontrar las clases Servlets y JSP
cuando compilemos nuestro fichero servlet. Las instrucciones de instalación del
JSWDK explican esto, pero básicamente apuntan a poner los ficheros servlet.jar y
jsp.jar (que vienen con el JSWDK) en nuestro CLASSPATH. Si nunca antes has
tratado con el CLASSPATH, es la variable de entorno que especifica donde Java
busca la clases. Si no es especificada, Java busca en el directorio actual y en las
librerías estándard del sistema. Si la seleccionamos nosotros mismos necesitamos
estar seguros de incluir ".", que significa el directorio actual. Aquí tenemos un
rápido sumario de cómo seleccionarla en un par de plataformas:
Unix (C Shell)
Windows 95/98/NT
set CLASSPATH=.;servlet_dir/servlet.jar;servlet_dir/jsp.jar
Añadimos ";%CLASSPATH%" al final de la línea anterior si nuestro CLASSPATH
ya está configurado. Observa que usamos puntos y coma ";" para separar
directoriois, mientras que en Unix se usan dos puntos. Para hacer permanente esta
configuración ponemos esta sentencias en el fichero autoexec.bat. En Windows
NT, vamos al menú Start, seleccionamos Settings y luego Control Panel,
seleccionamos System, y Environment y luego introducimos la variable y el valor.
Finalmente, como veremos en La siguiente sección, queremos poner nuestros
servlets en paquetes para evitar conflictos de nombres con los servlets escritos por
otras personas para la misma aplicación Web o servidor. En este caso, podríamos
encontrar conveniente añadir el directorio de más alto nivel de nuestro paquete al
CLASSPATH. Puedes ver la sección Primeros Servlets para más detalles.
Ozito
Servlets y JSP
Primeros Servlets
1. Estructura Básica de un Servlet
2. Un sencillo Servlet que Genera Texto Normal
3. Un Servlet que Genera HTML
4. Utilidades de Construcción de HTML Sencillo
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
2.1 HelloWorld.java
También puedes descargar el código fuente
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
DOS> cd C:\JavaWebServer\servlets
DOS> javac hall\YourServlet.java
Finalmente otra opción avanzada es mantener el código fuente en una localización
distinta de los ficheros .class. y usar la opción "-d" de javac para instalarlos en la
localización que espera el servidor Web.
3.1 HelloWWW.java
También puedes descargar El Código fuente.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
package hall;
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
Ozito
Servlets y JSP
Manejar Datos de Formularios
1. Introducción
2. Ejemplo: Leer Tres Parámetros
3. Ejemplo: Listar Todos los Datos del Formulario
1. Introducción
Si alguna vez has usado un motor de búsqueda Web, visitado un tienda de libros on-line, etc., probablemente
habrás encontrado URLs de búsqueda divertidas como
http://host/path?user=Marty+Hall&origin=bwi&dest=lax. La parte posterior a la interrogación
(user=Marty+Hall&origin=bwi&dest=lax) es conocida como datos de formulario, y es la forma más común de
obtener datos desde una página Web para un programa del lado del servidor. Puede añadirse al final de la URL
después de la interrogación (como arriba) para peticiones GET o enviada al servidor en una línea separada, para
peticiones POST.
Extraer la información necesaria desde estos datos de formulario es tradicionalmente una de las partes más
tediosas de la programación CGI.
Primero de todo, tenemos que leer los datos de una forma para las peticiones GET (en CGI tradicional, esto se
hace mediante QUERY_STRING), y de otra forma para peticiones POST (normalmente leyendo la entrada
estándard).
Segundo, tenemos que separar las parejas de los ampersands, luego separar los nombres de los parámetros (a la
izquierda de los signos igual) del valor del parámetro (a la derecha de los signos igual).
Tercero, tenemos que decodificar los valores. Los valores alfanuméricos no cambian, pero los espacios son
convertidos a signos más y otros caracteres se convierten como %XX donde XX es el valor ASCII (o ISO Latin-1)
del carácter, en hexadecimal. Por ejemplo, si alguien introduce un valor de "~hall, ~gates, y ~mcnealy" en un
campo de texto con el nombre "users" en un formulario HTML, los datos serían enviados como
"users=%7Ehall%2C+%7Egates%2C+and+%7Emcnealy".
Finalmente, la cuarta razón que hace que el análisis de los datos de formulario sea tedioso es que los valores
pueden ser omitidos (por ejemplo, param1=val1¶m2=¶m3=val3) y un parámetro puede tener más
de un valor y que el mismo parámetro puede aparecer más de una vez (por ejemplo:
param1=val1¶m2=val2¶m1=val3).
Una de las mejores características de los servlets Java es que todos estos análisis de formularios son manejados
automáticamente. Simplemente llamamos al método getParameter de HttpServletRequest, y suministramos el
nombre del parámetro como un argumento. Observa que los nombres de parámetros son sensibles a la
mayúsculas. Hacemos esto exactamente igual que cuando los datos son enviados mediante GET o como si los
enviaramos mediante POST. El valor de retorno es un String correspondiente al valor uudecode de la primera
ocurrencia del parámetro. Se devuelve un String vacío si el parámetro existe pero no tiene valor, y se devuelve
null si no existe dicho parámetro. Si el parámetro pudiera tener más de un valor, como en el ejemplo anterior,
deberíamos llamar a getParameterValues en vez de a getParameter. Este devuelve un array de strings.
Finalmente, aunque en aplicaciones reales nuestros servlets probablemente tengan un conjunto específico de
nombres de parámetros por los que buscar. Usamos getParameterNames para esto, que devuelve una
Enumeration, cada entrada puede ser forzada a String y usada en una llamada a getParameter.
2.1 ThreeParams.java
También puedes descargar el código fuente. Nota: también usa ServletUtilities.java, mostrado anteriormente.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
3.1 ShowParameters.java
También puedes descargar el código fuente. Nota: también usa ServletUtilities.java, mostrado anteriormente.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Shows all the parameters sent to the servlet via either
* GET or POST. Specially marks parameters that have no values or
* multiple values.
*
3.2 ShowParameters
Aquí tenemos un formulario hTML que envía un número de parámetros a este servlet. Pulsa con el botón derecho
sobre el enlace al código fuente para descargar el HTML.
Usa POST para enviar los datos (como deberían hacerlo todos los formularios que tienen entradas PASSWORD),
demonstrando el valor de que los servlets incluyan tanto doGet como doPost.
PostForm.html
<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">A Sample FORM using POST</H1>
<FORM ACTION="/servlet/hall.ShowParameters"
METHOD="POST">
Item Number:
<INPUT TYPE="TEXT" NAME="itemNum"><BR>
Quantity:
<INPUT TYPE="TEXT" NAME="quantity"><BR>
Price Each:
<INPUT TYPE="TEXT" NAME="price" VALUE="$"><BR>
<HR>
First Name:
<INPUT TYPE="TEXT" NAME="firstName"><BR>
Last Name:
<INPUT TYPE="TEXT" NAME="lastName"><BR>
Middle Initial:
<INPUT TYPE="TEXT" NAME="initial"><BR>
Shipping Address:
<TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
Credit Card:<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Visa">Visa<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Master Card">Master Card<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Amex">American Express<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Discover">Discover<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Java SmartCard">Java SmartCard<BR>
Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
Repeat Credit Card Number:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
<CENTER>
<INPUT TYPE="SUBMIT" VALUE="Submit Order">
</CENTER>
</FORM>
</BODY>
</HTML>
3.3 Resultados del envío
Ozito
Servlets y JSP
Leer Cabeceras de Solicitud HTTP
1. Introducción a las Cabeceras de Solicitud
2. Leer Cabeceras de Solicitud desde Servlets
3. Ejemplo: Imprimir todas la Cabeceras
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Creates a table showing the values of all the CGI variables.
*
* Part of tutorial on servlets and JSP that appears at
* http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/
* 1999 Marty Hall; may be freely used or adapted.
*/
Ozito
Servlets y JSP
Códigos de Estado HTTP
1. Introducción
2. Especificar Códigos de Estado
3. Códigos de Estado HTTP 1.1 y sus Significados
4. Ejemplo: Motor de Búsqueda
1. Introducción
Cuando un servidor Web responde a una petición de un navegador u otro cliente Web, la
respuesta consiste típicamente en una línea de estado, algunas cabeceras de respuesta, una línea
en blanco, y el documento. Aquí tenemos un ejemplo mínimo:
HTTP/1.1 200 OK
Content-Type: text/plain
Hello World
La línea de estado consiste en la versión HTTP, y un entero que se interpreta como código de
estado, y un mensaje muy corto que corresponde con el código de estado. En la mayoría de los
casos, todas las cabeceras son opcionales excepto Content-Type, que especifica el tipo MIME del
documento que sigue. Aunque muchas respuestas contienen un documento, algunas no lo tienen.
Por ejemplo, las respuestas a peticiones HEAD nunca deberían incluir un documento, y hay una
gran variedad de códigos de estado que esencialmente indican fallos, y o no incluyen un
documento o sólo incluyen un pequeño "mensaje de error de documento".
Los servlets pueden realizar una variedad de tareas manipulando la línea de estado y las
cabeceras de respuesta. Por ejemplo, reenviar al usuario a otros sites; indicar que el documento
adjunto es una imagen, un fichero Acrobat, o (más comunmente) un fichero HTML; decirle al
usuario que se requiere una password para acceder al documento; etc. Esta sección explica
varios códigos de estados diferentes y como se pueden conseguir, mientras que la página
siguiente describe la cabeceras de respuesta.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
package hall;
class SearchSpec {
private String name, baseURL, numResultsSuffix;
4.3 SearchEngines.html
Pulsa con el botón derecho sobre el enlace al código fuente para descargar el fichero fuente.
<FORM ACTION="/servlet/hall.SearchEngines">
<CENTER>
Search String:
<INPUT TYPE="TEXT" NAME="searchString"><BR>
Results to Show Per Page:
<INPUT TYPE="TEXT" NAME="numResults"
VALUE=10 SIZE=3><BR>
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="google">
Google |
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="infoseek">
Infoseek |
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="lycos">
Lycos |
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="hotbot">
HotBot
<BR>
<INPUT TYPE="SUBMIT" VALUE="Search">
</CENTER>
</FORM>
</BODY>
</HTML>
1. Introducción
Una respuesta desde un servidor Web normalmente consiste en una línea de estado, una o
más cabeceras de respuesta, una línea en blanco, y el documento. Seleccionar las cabeceras
de respuesta normalmente va mano con mano con la selección de códigos de estado en la
línea de estado. Por ejemplo, muchos de los códigos de estado "document moved" tienen una
cabecera Location de acompañamiento, y un 401 (Unauthorized) debe incluir una cabecera
WWW-Authenticate.
Sin embargo, especificar las cabeceras puede jugar un rol muy útil cuando se selecciona
códigos de estado no usuales. Las cabeceras de respuesta se pueden usar para especificar
cookies, para suministrar la fecha de modificación (para el caché), para instruir al navegador
sobre la recarga de la página después de un intervalo designado, para decir cuanto tiempo va
a estar el fichero usando conexiones persisitentes, y otras muchas tareas.
La forma más general de especificar cabeceras es mediante el método setHeader de
HttpServletResponse, que toma dos strings: el nombre de la cabecera y el valor de ésta.
Igual que la selección de los códigos de estado, esto debe hacerse antes de envíar cualquier
documento.
Hay también dos métodos especializados para seleccionar cabeceras que contienen fechas
(setDateHeader) y enteros (setIntHeader). La primera nos evita el problema de tener que
traducir una fecha Java en milisegundos (como al devuelta por los métodos
System.currentTimeMillis o getTime aplicados a un objeto Date) en stirng GMT. El
segundo nos ahora la incoveniencia menor de convertir un int a un String.
En el caso de una cabecera cuyo nombre ya exista, podemos añadir una nueva cabecera en
vez de seleccionarla de nuevo. Usamos addHeader, addDateHeader, y addIntHeader para
esto. Si realmente nos importa si una cabecera específica se ha seleccionado, podemos usar
containsHeader para comprobarlo.
Finalmente, HttpServletResponse también suministra unos métodos de conveniencia para
especificar cabeceras comunes:
● El método setContentType selecciona la cabecera Content-Type, y se usa en la
mayoría de los Servlets.
● El método setContentLength selecciona la cabecera Content-Length, útil si el
navegador soporta conexiones HTTP persistentes (keep-alive).
● El método addCookie selecciona un cookie (no existe el correspondiente setCookie, ya
que es normal que haya varias líneas Set-Cookie).
● Y como se especificó en la página anterior, el método sendRedirect selecciona la
cabecera Location así como se selecciona el código de estado 302.
Para más detalles sobre cabeceras HTTP, puedes ver las especificaciones en
http://www.w3.org/Protocols/.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
3.3 PrimeNumbers.html
Nota: pulsa con el botón derecho sobre el enlace al código fuente.
<BODY BGCOLOR="#FDF5E6">
<H2 ALIGN="CENTER">Finding Large Prime Numbers</H2>
<BR><BR>
<CENTER>
<FORM ACTION="/servlet/hall.PrimeNumbers">
<B>Number of primes to calculate:</B>
<INPUT TYPE="TEXT" NAME="numPrimes" VALUE=25 SIZE=4><BR>
<B>Number of digits:</B>
<INPUT TYPE="TEXT" NAME="numDigits" VALUE=150 SIZE=3><BR>
<INPUT TYPE="SUBMIT" VALUE="Start Calculating">
</FORM>
</CENTER>
</BODY>
</HTML>
3.4 Inicio
[ ] ( ) = , " / ? @ : ;
package hall;
import javax.servlet.http.*;
4.1 SearchEnginesFrontEnd.java
Este servlet construye la página del formulario para el servlet del motor de búsqueda. A primera
vista, se parece a la página vista en la página HTML estática presentada en la página anterior. Sin
embargo, aquí, se recuerdan los valor seleccionados en cookies (seleccionado por el servlet
CustomizedSearchEngines a los que está página envía los datos), por eso si el usuario vuelve a la
misma página después de algún tiempo (incluso después de apagar el navegador), la página se
inicializa con los valores de la búsqueda anterior.
También puedes descargar el código fuente.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
4.2 CustomizedSearchEngines.java
El servlet anterior SearchEnginesFrontEnd envía sus datos al servlet CustomizedSearchEngines.
En muchos aspectos, es igual que el servlet SearchEngines mostrado en la página anterior. Sin
embargo, además de construir una URL para un motor de búsqueda y envíar una redirección de
respuesta al cliente, el servlet también envía cookies recordando los datos del usuario. Estos cookies,
serán utilizados por el servelt para construir la página para inicializar las entradas del formulario
HTML.
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
import java.util.*;
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" +
"<H2>Information on Your Session:</H2>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
" <TH>Info Type<TH>Value\n" +
"<TR>\n" +
" <TD>ID\n" +
" <TD>" + session.getId() + "\n" +
"<TR>\n" +
" <TD>Creation Time\n" +
" <TD>" + new Date(session.getCreationTime()) + "\n" +
"<TR>\n" +
" <TD>Time of Last Access\n" +
" <TD>" + new Date(session.getLastAccessedTime()) + "\n" +
"<TR>\n" +
" <TD>Number of Previous Accesses\n" +
" <TD>" + accessCount + "\n" +
"</TABLE>\n" +
"</BODY></HTML>");
1. Introducción
Las JavaServer Pages (JSP) nos permiten separar la parte dinámica de nuestras páginas Web del
HTML estático. Simplemente escribimos el HTML regular de la forma normal, usando cualquier
herramienta de construcción de paginas Web que usemos normalmente. Encerramos el código de las
partes dinámicas en unas etiquetas especiales, la mayoría de las cuales empiezan con "<%" y
terminan con "%>". Por ejemplo, aquí tenemos una sección de una página JSP que resulta en algo
así como "Thanks for ordering Core Web Programming" para una URL como
http://host/OrderConfirmation.jsp?title=Core+Web+Programming:
2. Sumario de Síntaxis
Elemento JSP Síntaxis Interpretación Notas
El equivalente XML es
<jsp:expression>
La Expresión es
expression
evaluada y
Expresión JSP <%= expression %> </jsp:expression>.
situada en la
Las variables predefinidas son request,
salida.
response, out, session, application, config,
y pageContext.
El código se El equivalente XML es:
inserta en el <jsp:scriptlet>
Scriptlet JSP <% code %>
método code
service. </jsp:scriptlet>.
El código se
inserta en el
El equivalente XML es:
cuerpo de la
<jsp:declaration>
Declaración JSP <%! code %> clase del
code
servlet, fuera
</jsp:declaration>.
del método
service.
El equivalente XML es:
<jsp:directive.page att="val"\>.
Los atributos legales son (con los valores por
defecto en negrita):
● import="package.class"
● contentType="MIME-Type"
● isThreadSafe="true|false"
Dirige al motor
Directiva page servlet sobre la ● session="true|false"
<%@ page att="val" %>
JSP configuración ● buffer="sizekb|none"
general.
● autoflush="true|false"
● extends="package.class"
● info="message"
● errorPage="url"
● isErrorPage="true|false"
● language="java"
El equivalente XML es:
Un fichero del
<jsp:directive.include
sistema local se
file="url"\>.
Directiva incluirá cuando
<%@ include file="url" %> La URL debe ser relativa. Usamos la acción
include JSP la página se
jsp:include para incluir un fichero en el
traduzca a un
momento de la petición en vez del momento de
Servlet.
la tradución.
Comentario
ignorado
Si queremos un comentario en el HTML
cuando se
Comentario JSP <%-- comment --%> resultante, usamos la síntaxis de comentario
traduce la
normal del HTML <-- comment -->.
página JSP en
un servlet.
Incluye un
Aviso: en algunos servidores, el fichero incluido
<jsp:include fichero en el
Acción debe ser un fichero HTML o JSP, según
page="relative URL" momento en
jsp:include determine el servidor (normalmente basado en
flush="true"/> que la página
la extensión del fichero).
es solicitada.
Los posibles atributos son:
<jsp:useBean att=val*/> ● id="name"
o Encuentra o ● scope="page|request|session|application"
Acción <jsp:useBean att=val*> construye un
jsp:useBean class="package.class"
... Java Bean. ●
</jsp:useBean> ● type="package.class"
● beanName="package.class"
Selecciona las
propiedades del Los atributos legales son:
bean, bien
● name="beanName"
directamenteo
Acción <jsp:setProperty att=val*/> o designando el ● property="propertyName|*"
jsp:setProperty
valor que viene ● param="parameterName"
desde un
parámetro de la ● value="val"
petición.
<jsp:getProperty Recupera y
Acción name="propertyName" saca las
jsp:getProperty value="val"/> propiedades del
Bean.
Reenvía la
Acción <jsp:forward
petición a otra
jsp:forward page="relative URL"/>
página.
Genera
etiquetas
OBJECT o
<jsp:plugin EMBED,
apropiadas al
Acción attribute="value"*>
tipo de
jsp:plugin ...
</jsp:plugin> navegador,
pidiendo que se
ejecute un
applet usando
el Java Plugin.
La única excepción a la regla de que "la plantilla de texto se pasa tal y como es" es que, si queremos tener "<%" en
la salida, necesitamos poner "<\%" en la plantilla de texto.
● response, el HttpServletResponse;
● session, el HttpSession asociado con el request (si existe), y
● out, el PrintWriter (una versión con buffer del tipo JspWriter) usada para envíar la salida al cliente.
Aquí tenemos un ejemplo:
<jsp:expression>
Expresión Java
</jsp:expression>
Recuerda que los elementos XML, al contrario que los del HTML, son sensibles a las mayúsculas; por eso asegúrate
de usar minúsculas.
<%
String queryData = request.getQueryString();
out.println("Attached GET data: " + queryData);
%>
Observa que el código dentro de un scriptlet se insertará exactamente como está escrito, y cualquier HTML estático
(plantilla de texto) anterior o posterior al scriptlet se convierte en sentencias print. Esto significa que los scriptlets no
necesitan completar las sentencias Java, y los bloques abiertos pueden afectar al HTML estático fuera de los scriplets.
Por ejemplo, el siguiente fragmento JSP, contiene una mezcla de texto y scritplets:
<jsp:scriptlet>
Código
</jsp:scriptlet>
<jsp:declaration>
Código
</jsp:declaration>
5. Directivas JSP
Una directiva JSP afecta a la estructura general de la clase servlet. Normalmente tienen la siguiente forma:
Por ejemplo, muchas sites incluyen una pequeña barra de navegación en cada página. Debido a los problemas con los
marcos HTML, esto normalmente se implementa mediante una pequeña tabla que cruza la parte superior de la página
o el lado izquierdo, con el HTML repetido para cada página de la site. La directiva include es una forma natural de
hacer esto, ahorrando a los desarroladores el mantenimiento engorroso de copiar realmente el HTML en cada fichero
separado. Aquí tenemos un código representativo:
<BODY>
<%@ include file="/navbar.html" %>
</BODY>
</HTML>
Observa que como la directiva include inserta los ficheros en el momento en que la página es traducida, si la barra
de navegación cambia, necesitamos re-traducir todas las páginas JSP que la refieren. Esto es un buen compromiso en
una situación como esta, ya que las barras de navegación no cambian frecuentemente, y queremos que el proceso de
inclusión sea tan eficiente como sea posible. Si, sin embargo, los ficheros incluidos cambian de forma más frecuente,
podríamos usar la acción jsp:include en su lugar. Esto incluye el fichero en el momento en que se solicita la página
JSP, como se describe en la sección 8.
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429">
<TR><TH CLASS="TITLE">
Using JavaServer Pages</TABLE>
</CENTER>
<P>
7. Variables Predefinidas
Para simplififar el código en expresiones y scriplets JSP, tenemos ocho variables definidas automáticamente, algunas
veces llamadas objetos implícitos. Las variables disponibles son: request, response, out, session, application,
config, pageContext, y page.
7.1 request
Este es el HttpServletRequest asociado con la petición, y nos permite mirar los parámetros de la petición (mediante
getParameter), el tipo de petición (GET, POST, HEAD, etc.), y las cabeceras HTTP entrantes (cookies, Referer,
etc.). Estrictamente hablando, se permite que la petición sea una subclase de ServletRequest distinta de
HttpServletRequest, si el protocolo de la petición es distinto del HTTP. Esto casi nunca se lleva a la práctica.
7.2 response
Este es el HttpServletResponse asociado con la respuesta al cliente. Observa que, como el stream de salida (ver
out más abajo) tiene un buffer, es legal seleccionar los códigos de estado y cabeceras de respuesta, aunque no está
permitido en los servlets normales una vez que la salida ha sido envíada al cliente.
7.3 out
Este es el PrintWriter usado para envíar la salida al cliente. Sin embargo, para poder hacer útil el objeto response
(ver la sección anterior), esta es una versión con buffer de PrintWriter llamada JspWriter. Observa que podemos
ajustar el tamaño del buffer, o incluso desactivar el buffer, usando el atributo buffer de la directiva page. Esto se
explicó en la Sección 5. También observa que out se usa casi exclusivamente en scriptlets ya que las expresiones JSP
obtienen un lugar en el stream de salida, y por eso raramente se refieren explícitamente a out.
7.4 session
Este es el objeto HttpSession asociado con la petición. Recuerda que las sesiones se crean automáticamente, por
esto esta variable se une incluso si no hubiera una sesión de referencia entrante. La única excepción es usar el
atributo session de la directiva page (ver la Sección 5) para desactivar las sesiones, en cuyo caso los intentos de
referenciar la variable session causarán un error en el momento de traducir la página JSP a un servlet.
7.5 application
Este es el ServletContext obtenido mediante getServletConfig().getContext().
7.6 config
Este es el objeto ServletConfig para esta página.
7.7 pageContext
JSP presenta una nueva clase llamada PageContext para encapsular características de uso específicas del servidor
como JspWriters de alto rendimiento. La idea es que, si tenemos acceso a ellas a través de esta clase en vez
directamente, nuestro código seguirá funcionando en motores servlet/JSP "normales".
7.8 page
Esto es sólo un sinónimo de this, y no es muy útil en Java. Fue creado como situación para el día que el los lenguajes
de script puedan incluir otros lenguajes distintos de Java.
8. Accciones
Las acciones JSP usan construcciones de síntaxis XML para controlar el comportamiento del motor de Servlets.
Podemos insertar un fichero dinámicamente, reutilizar componentes JavaBeans, reenviar al usuario a otra página, o
generar HTML para el plug-in Java. Las acciones disponibles incluyen:
● jsp:include - Incluye un fichero en el momento de petición de esta página. Ver la Sección 8.1.
● jsp:useBean - Encuentra o ejemplariza un JavaBean. Ver la Sección 8.2 para una introducción, y la Sección
8.3 para los detalles.
● jsp:setProperty - Selecciona la propiedad de un JavaBean. Ver la Sección 8.4.
● jsp:getProperty - Inserta la propiedad de un JavaBean en la salida. Ver la Sección 8.5.
● jsp:forward - Reenvía al peticionario a una nueva página. Ver la Sección 8.6.
● jsp:plugin - Genera código específico del navegador que crea una etiqueta OBJECT o EMBED para el plug-in
Java. Ver la Sección 8.7.
Recuerda que, como en XML, los nombre de elementos y atributos son sensibles a las mayúsculas.
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429">
<TR><TH CLASS="TITLE">
What's New at JspNews.com</TABLE>
</CENTER>
<P>
Ahora, una vez que tenemos un bean, podemos modificar sus propiedades mediante jsp:setProperty, o usando un
scriptlet y llamando a un método explícitamente sobre el objeto con el nombre de la variable especificada
anteriormente mediante el atributo id. Recuerda que con los beans, cuando decimos "este bean tiene una propiedad
del tipo X llamada foo", realmente queremos decir "Esta clase tiene un método getFoo que devuelve algo del tipo X,
y otro método llamado setFoo que toma un X como un argumento". La acción jsp:setProperty se describe con más
detalle en la siguiente sección, pero ahora observemos que podemos suministrar un valor explícito, dando un
atributo param para decir que el valor está derivado del parámetro de la petición nombrado, o sólo lista las
propiedades para indicar que el valor debería derivarse de los parámetros de la petición con el mismo nombre que la
propiedad. Leemos las propiedades existentes en una expresión o scriptlet JSP llamando al método getXxx, o más
comunmente, usando la acción jsp:getProperty.
Observa que la clase especificada por el bean debe estar en el path normal del servidor, no en la parte reservada que
obtiene la recarga automática cuando se modifican. Por ejemplo, en el Java Web Server, él y todas las clases que usa
deben ir en el directorio classes o estar en un fichero JAR en el directorio lib, no en el directorio servlets.
Aquí tenemos un ejemplo muy sencillo que carga un bean y selecciona y obtiene un sencillo parámetro String.
BeanTest.jsp
También puedes descargar el código fuente.
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
Reusing JavaBeans in JSP</TABLE>
</CENTER>
<P>
<H1>Message: <I>
<jsp:getProperty name="test" property="message" />
</I></H1>
</BODY>
</HTML>
SimpleBean.java
Aquí está el código fuente usado para el Bean usado en la página BeanTest. También puedes descargar el código
fuente.
package hall;
<jsp:useBean ...>
Body
</jsp:useBean>
Para indicar que la porción Body sólo se debería ejecutar cuando el bean es ejemplarizado por primera vez, no
cuando un bean existente se encuentre y se utilice. Como se explica abajo, los bean pueden ser compartidos, por eso
no todas las sentencias jsp:useBean resultan en la ejemplarización de un Bean. Segundo, además de id y class,
hay otros tres atributos que podemos usar: scope, type, y beanName.
Atributo Uso
Da un nombre a la variable que referenciará el bean. Se usará un objeto bean anterior
id en lugar de ejemplarizar uno nuevo si se puede encontrar uno con el mismo id y
scope.
class Designa el nombre completo del paquete del bean.
Indica el contexto en el que el bean debería estar disponible. Hay cuatro posibles
valores: page, request, session, y application. El valor por defecto, page, indica
que el bean estará sólo disponible para la página actual (almacenado en el
PageContext de la página actual). Un valor de request indica que el bean sólo está
disponible para la petición actual del cliente (almacenado en el objeto
ServletRequest). Un valor de session indica que el objeto está disponible para todas
scope las páginas durante el tiempo de vida de la HttpSession actual. Finalmente, un valor
de application indica que está disponible para todas las páginas que compartan el
mismo ServletContext. La razón de la importancia del ámbito es que una entrada
jsp:useBean sólo resultará en la ejemplarización de un nuevo objeto si no había
objetos anteriores con el mismo id y scope. De otra forma, se usarán los objetos
existentes, y cualquier elemento jsp:setParameter u otras entradas entre las
etiquetas de inicio jsp:useBean y la etiqueta de final, serán ignoradas.
Especifica el tipo de la variable a la que se referirá el objeto. Este debe corresponder
type con el nombre de la clase o ser una superclase o un interface que implemente la clase.
Recuerda que el nombre de la variable se designa mediante el atributo id.
Da el nombre del bean, como lo suministraríamos en el método instantiate de Beans.
beanName
Esta permitido suministrar un type y un beanName, y omitir el atributo class.
JspPrimes.jsp
Para descargar el código JSP, pulsa con el botón derecho sobre el enlace.
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
Reusing JavaBeans in JSP</TABLE>
</CENTER>
<P>
</BODY>
</HTML>
Aquí tenemos un resultado típico:
8.5 Acción jsp:getProperty
Este elemento recupera el valor de una propiedad del bean, lo convierte a un string, e inserta el valor en la salida.
Los dos atributos requeridos son name, el nombre de un bean referenciado anteriormente mediante jsp:useBean, y
property, la propiedad cuyo valor debería ser insertado. Aquí tenemos un ejemplo:
<jsp:useBean id="itemBean" ... />
...
<UL>
<LI>Number of items:
<jsp:getProperty name="itemBean" property="numItems" />
<LI>Cost of each:
<jsp:getProperty name="itemBean" property="unitCost" />
</UL>
Ozito
Introducción a JSP
Las JavaServer Pages (JSP) están basadas en la tecnología de servlets. Cuando se
combina con el uso de componentes JavaBeans, JSP promete proporcionar una
capacidad que es al menos tan poderosa como los Servlets, posiblemente más que
un servelt en crudo, y potencialmente mucho más fácil de usar.
Instalación y Configuración
Cuando descarguemos el JSWDK, encontraremos que se nos proporciona mucha
información para ayudarnos a instalar y configurar el servidor. En algún momento
deberemos leer esta documentación. Sin embargo, para que obtengas un arranque
rápido vamos a mostrarte como configurar el servidor web en una máquina WinNT.
Deberías poder configurar de una forma similar tu máquina y ver las primeras
demostraciones de JSP muy rápidamente.
d:\Program Files\jswdk-1.0.1
El nombre del directorio más alto en el árbol de directorios es jswdk-1.0.1. Con el
tiempo, con la liberaciónde nuevas versiones, el nombre de este directorio seguro
que cambiará.
¿Qué pasa con el JDK?
Cuando usamos nuestro navegador para solicitar una página JSP desde el servidor,
éste debe crear y compilar un servlet. El servidor jswdk no contiene un compilador
ni una máquina virtual. Por lo tanto, si no lo tenemos ya instalado, debemos
instalar el JDK para que el servidor lo use para compilar y ejecutar el servlet.
En el momento de escribir esto, tengo instalada la versión JDK 1.2.2 en mi
máquina. El Path al directorio de más alto nivel del JDK es:
d:\Program Files\jdk1.2.2
Mi instalaciónes completamente estándard (según Sun) excepto en que la tengo
instalada en el disco D en lugar del disco C.
d:\Program Files\jdk1.2.2\lib\tools.jar
Este elemento identifica la localización del fichero JAR que contiene las librerías de
clases estándars del JDK.
Como también uso el JSWDK como motor de servlet (independiente del JDP),
también necesito el siguiente elemento en el classpath:
d:\Program Files\jswdk-1.0.1\lib\servlet.jar
Este elemento identifica la localización del fichero jar que contiene los distintos
componentes de software necesarios para compilar y ejecutar servlets.
(la parte inicial de tu path podría ser diferente, dependiendo de donde situaras el
JSWDK en tu disco duro).
d:\Program Files\jswdk-1.0.1\startserver.bat
Deberíamos parar el servidor ejecutando el siguiente fichero batch:
d:\Program Files\jswdk-1.0.1\stopserver.bat
He situado accesos directos a estos ficheros bacth en mi escritorio para arrancar y
parar el servidor fácilmente.
Ficheros Temporales
http://localhost:8080/jsp001.jsp
Podríamos necesitar estar online para que esto funciones. En caso de que no
funciones, necesitaremos estudiar la documentación del JSWDK para aprender
otras formas alternativas para direccionar el servidor.
Acceder a un Fichero HTML
http://localhost:8080/jsp001.htm
Ozito
Directivas JSP
¿Qué es la Directiva Include?
La directiva include se usa para insertar un fichero dentro de una página JSP
cuando se compila la página JSP. El texto del fichro incluido se añade a la página
JSP (ver la descripción de un fichero estático más adelante en esta página)
Si el fichero incluido es un fichero JSP, las etiquetas JSP son analizadas y sus
resultados se incluyen (junto con cualquier otro texto) en el fichero JSP.
Sólo podemos incluir ficheros estaticos. Esto significa que el resultado analizado del
fichero incluido se añade al fichero JSP justo donde está situada la directiva. Una
vez que el fichero incluido es analizado y añadido, el proceso continúa con la
siguiente línea del fichero JSP llamante.
Un include estático significa que el texto del fichero incluido se añade al fichero
JSP.
Además en conjuncióncon otra etiqueta JSP, <jsp:include>: podemos incluir
ficheros estáticos o dinámicos:
Un fichero estático es analizado y si contenido se incluye en la página JSP
llamante.
Un fichero dinámico actúa sobre la solicitud y envía de vuelta un resultado que es
incluido en la página JSP.
¿Cuál es la Sintasis para Incluir un Fichero?
Podemos incluir unfichero en la localización específica del fichero JSP usando la
directiva include con la siguiente síntasis::
<%@ page
[ language="java"]
[ extends="package.class"]
[ import= "{ package.class|package.*}, ..." ]
[ session="true|false"]
[ buffer="none|8kb|sizekb"]
[ autoFlush="true|false"]
[ isThreadSafe="true|false"]
[ info="text"]
[ errorPage="URLrelativa"]
[ contentType="mimeType[ ;charset=characterSet]" |
"text/html; charset=ISO-8859-1"]
[ isErrorPage="true|false"]
%>
<tr>
<td height="150" width="150"> </td>
<td width="250"> </td>
</tr>
<tr>
<td width="150"> </td>
<td align="right" width="250">
</table>
<br>
<html>
<head><title>Hello, World</title></head>
<body bgcolor="#ffffff" background="background.gif">
<table>
<tr>
<td width=150> </td>
<td width=250 align=right> <h1>Hello, World!</h1> </td>
</tr>
</table>
</body>
</html>
La Directiva Page
La directiva Page es una etiqueta JSP que usaremos encaso todos los ficheros
fuente JSP que escribamos. En helloworld.jsp, es la línea que se parece a esto:
La Directiva Include
La directiva include inserta el contenido de otro fichero en el fichero principal JSP,
donde está situada la directiva. Es útil para incluir informaciónde copuright,
ficheros de lenguaje de script, p cualquier cosa que podríamos querer reutilizar en
otras aplicaciones. En este ejemplo, el fichero incluido es una tabla qu crea un
banner gráfico.
Podemos ver el contenido del fichero incluido viendo la página fuente del fichero
principal JSP mientras estamos ejecutando Hello, World. El fichero incluido no
contiene etiquetas <html> o <body>, porque podrían generar conflictos con las
mismas etiquetas del fichero JSP llamante.
Una Nota sobre las Etiquetas JSP
Cuando uses los ejemplos de este capítulo, recuerda que las etiquetas JSP son
sensibles a las mayúscula. Si, por ejemplo, tecleamos <jsp:usebean> en lugar de
<jsp:useBean>, nuestra etiqueta no será reconocida, y la implementación de
referencia JSP 1.0 lanzará una excepción. Algunos de los atributos de las etiquetas
toman nombres de clases, nombres de paquetes, pathnames o otros valores
también sensibles a las mayúsculas.
Ozito
Manejar Formularios HTML
Una de las partes más comunes de una aplicación de comercio electrónico es un
formulario HTML en el que un usuario introduce alguna información. La información
podría ser un nombre de cliente y su dirección, una palabra o frase introducida
para un motor de búsqueda, o un conjunto de preferencias lanzadas como datos
del mercado.
El motor JSP envía el objeto solicitado a cualquier componente del lado del servidor
(JavaBeansTM , servlet, o bean enterprise) que especifica el JSP. El componente
maneja la solicitud, posiblemente recuperando datos desde una base de datos u
otros datos almacenados, y pasa un objeto respuesta de vuelta la motor JSP,
donde los datos se formatean de acuerdo al diseño de la página HTML. El motor
JSP y el servidor Web entonces envían la página JSP revisada de vuelta al cliente,
donde el usuario puede ver el resultado, en el navegador Web. Los protocolos de
comunicación usados entre el cliente y el servidor pueden ser HTTP, o cualquier
otro protocolo.
Los objetos request y response están siempre implícitamente disponibles para
nosotros como autores de ficheros fuentes JSP. El objeto request se explica con
más detalle más adelante en este tutorial.
Código de Ejemplo
El Banner Duke (dukebanner.html)
<html>
<head><title>Hello, User</title></head>
<body bgcolor="#ffffff" background="background.gif">
<%
if ( request.getParameter("username") != null ) {
%>
<%
}
%>
</body>
</html>
El fichero de Respuesta (response.jsp)
<td width="550">
</td>
</tr>
</table>
El Bean que Maneja los Datos del Formulario (namehandler.java)
package hello;
public class NameHandler {
public NameHandler() {
username = null;
}
Un formulario HTML tiene tres partes principales: las etiquetas de apertura y cierre
<form>, los elementos de entrada, y el botón Submit que envía los datos al
servidor. En una página normal HTML, la etiqueta de apertura <form>
normalmente se parecerá a algo como esto:
Los métodos HTTP GET y POST envían datos al servidor. En una Aplicación JSP,
GET y POST envían los datos a un Bean, servlet, u otro componente del lado del
servidor que está manejando los datos del formulario.
En teoría, GET es para obtener datos desde el servidor y POST es para envíar
datos. Sin embargo, GET añade los datos del formulario (llamada una query
string (string de solicitud)) a una URL, en la forma de parejas clave/valor desde
el formulario HTML, por ejemplo, name=john. En el String de solicitud las parejas
de clave/valor se separán por caracterres &, los espacios se convierten en
caracteres +, y los caracteres especiales se convierten a sus correspondientes
hexadecimales. Como el String de solicitud está en la URL,la página puede ser
añadida a los bookmarks o envíada por e-mail con el string de solicitud. Este string
normalmente está limitado a un número relativamente pequeño de caracteres.
Sin embargo, el método POST, pasa los datos de una longitud ilimitada como un
cuerpo de solicitud de cabecera HTTP hacia el servidor. El usuario que trabaja en el
navegador cliente no puede ver los datos que están siendo enviados, por eso la
solicitud POST es ideal para enviar datos confidenciales (como el número de una
tarjeta de crédito) o grandes cantidades de datos al servidor.
Escribir el Bean
Una vez que los datos del usuario han siso enviados al Bean, podriamos querer
recuperar los datos y mostrarlos en la página JSP. Para hacer esto, usamos la
etiqueta <jsp:getProperty>, dándole el nombre del Bean y el nombre de la
propiedad:
hellouser.jsp:
<jsp:useBean id="mybean" scope="session"
class="hello.NameHandler" />
<jsp:setProperty name="mybean" property="*" />
response.jsp:
<h1>Hello, <jsp:getProperty name="mybean"
property="username"/>!
En este ejemplo, las etiquetas están en dos ficheros, pero los nombres de los Bean
son iguales. Si no fuera así, la implementación de referencia del JSP lanzará un
error.
Las respuesta que el motor JSP devuelve al cliente está encapsulada en el objeto
response implícito, que crea el motor JSP.
Ozito
Usar Elementos de Scripting
En el algún momento, probablemente querramos añadir algún viejo código a
nuestras ficheros JSP. Las etiquetas JSP son poderosas y encapsulan tareas que
serían difíciles o llevarián mucho tiempo de programar. Pero por eso,
probablemente querramos usar fragmentos de lenguaje de script para suplementar
las etiquetas JSP.
Los lenguajes de script que tenemos disponibles dependen del motor JSP que
estemos usando. Con la implementación JSP de Sun, debemos usar el lenguaje
Java como lenguaje de script, pero otros motores de JSP de terceras partes
podrían incluir soporte para otros lenguajes.
<%
String name = null;
if (request.getParameter("name") == null) {
%>
Recuerda que en un scriptlet debemos terminar una sentencia de lenguaje con un
punto y coma si el lenguaje los requiere.
Cuando escribamos un scriptlet podemos usar cualquiera de los objetos o clases
implícitos de JSP importados por la directiva page, declarada en una declaración, o
nombrada en una etiqueta <jsp:useBean> .
<!--
Number Guess Game
Written by Jason Hunter, CTO, K&A Software
[email protected], http://www.servlets.com
Copyright 1999, K&A Software
Distributed by Sun Microsystems with permission
-->
<html>
<head><title>Number Guess</title></head>
<body bgcolor="white">
<font size=4>
<form method=get>
What's your guess? <input type=text name=guess>
<input type=submit value="Submit">
</form>
<form method=get>
What's your guess? <input type=text name=guess>
<input type=submit value="Submit">
</form>
<% } %>
</font>
</body>
</html>
Manejar el Guess (NumberGuessBean.java)
package num;
import java.util.*;
public class NumberGuessBean {
int answer;
boolean success;
String hint;
int numGuesses;
public NumberGuessBean() {
reset();
}
int g;
try {
g = Integer.parseInt(guess);
}
catch (NumberFormatException e) {
g = -1;
}
if (g == answer) {
success = true;
}
else if (g == -1) {
hint = "a number next time";
}
else if (g < answer) {
hint = "higher";
}
else if (g > answer) {
hint = "lower";
}
}
public boolean getSuccess() {
return success;
}
<% } %>
<!-- reabrimos el scriptlet para cerrar el bloque de lenguaje-->
Al principio, esto podría parecer un poco extraño, pero así se asegura de que los
elementos de scripting son transformados correctamente cuando se compila el
fichero fuente JSP.
Ozito
Manejar Excepciones
¿Que sucedió la última vez que usamos una aplicación JSP e introdujimos algo
incorrectamente? Si la aplicación estaba bien escrita, probablemente lanzaría una
excepción y mostraría una página de error. Las excepciones que ocurren durante la
ejecución de una aplicación JSP se llaman excepciones en tiempo de ejecución y se
describen en este tutorial.
Al igual que en una aplicación Java, una excepción es un objeto que es un ejemplar de
java.lang.Throwable o de una de sus subclases. Throwable tiene dos subclases
estándards -java.lang.Exception, que describe excepciones, y java.lang.Error, que
describe errores.
Los errores son diferentes de las excepciones. Los errores normalmente indican
problemas de enlaces o de la máquina virtual de los que nuestra aplicación Web podría
no recuperarse, como errores de memoria. Sin embargo, las excepciones son
condiciones que pueden capturarse y recuperarse de ellas. Estas excepciones podrían
ser, por ejemplo, un NullPointerException o un ClassCastException, que nos dicen
que se ha pasado un valor nulo o un dato del tipo erróneo a nuestra aplicación
mientras se estaba ejecutando.
Las excepciones en tiempo de ejecución son fáciles de menejar en una aplicación JSP,
porque estan almacenadas una cada vez en el objeto implícito llamado exception.
Podemos usar el objeto exception en un tipo especial de página JSP llamado página
de error, donde mostramos el nombre de la clase exception, su seguimiento de pila, y
un mensaje informativo para el usuario.
Las excepciones en tiempo de ejecución son lanzadas por el fichero JSP compilado, el
fichero class Java que contiene la versión traducida de nuestra página JSP. Esto
significa que nuestra aplicación ha sido compilada y traducida correctamente. (Las
excepciones que ocurren mientras un fichero está siendo compilado o traducido no son
almacenadas en el objetoexception y tienen sus mensajes mostrados en la ventana
de comandos, en vez de en la página de error. Estas no son el tipo de excepciones
descritas en este tutorial.)
Este tutorial describe cómo crear una sencilla aplicación JSP con varias páginas, un
componente JavaBean y una página de error que ofrece mensajes informativos al
usuario. En este ejemplo, el Bean sigue la pista sobre la página en la que estaba
trabajando el usuario cuando se lanzó la excepción, que nos da a nosotros, el
desarrollador, información útil para que podamos mostrar un mensaje informativo.
Este es un simple mecanismo de seguimiento de error.
¿Cómo Añadir Páginas de Error?
Aunque las llamemos páginas de error, las páginas especializadas JSP que describimos
aquí realmente muestran información sobre excepciones. Para añadir páginas de error
que muestren información de excepciones a una aplicación web, seguimos estos
pasos:
● Escribimos nuestro Bean (o bean enterprise, servlet, u otro componente) para
que lance ciertas excepcioens bajo ciertas condiciones.
● Usamos un sencillo mecanismo de seguimiento en nuestro componente para
ayudarnos a obtener información sobre lo que estaba haciendo el usuario cuando
la excepción fue lanzada. (Si nos movemos en el desarrollo de aplicaciones J2EE,
nuestra aplicación podrá grabar el estado, que es la mejor forma de proporcionar
información).
● El fichero JSP usa una directiva page con errorPage que selecciona el nombre
de un fichero JSP que mostrará un mensaje al usuario cuando ocurre una
excepción.
● Escribir un fichero de página de error, usando una directiva page con
isErrorPage="true".
● En el fichero de la página de error, usa el objeto exception para obtener
información sobre la excepción.
● Usamos mensajes informativos, en nuestra página de error o incluida desde otros
ficheros, para darle al usuario un mensaje relevantemente informativo sobre lo
que el usuario estaba haciendo cuando se lanzó la excepción.
Para aquellos que seamos curiosos sobre algoritmos, un árbol rojo-negro es un arbol
binario extendido que se parece a algo similar a esto (conceptualmente, al menos):
Si estas viendo este documento en la pantalla, veras que algunos nodos
son rojos y otros on negros.
El árbol rojo-negro tiene nodos que pueden ser ramas u hojas. Los nodos hojas son
los nodos que hay al final de una línea, mientras que los nodos ramas son los nodos
más grandes que conectan con dos o más líneas. Los nodos se almacenan en una
estructura compensada en el árbol, usando las siguientes condiciones:
● Cada nodo tiene dos hijos o es una hoja.
● Cada camino desde el raíz hasta una hoja contiene el mismo número de nodos
negros.
La ventaja de un árbol, para nosotros, los desarrolladores Web, es que podemos crear
un fichero map que almacena datos en orden ascendente (ordenados por claves) y
que tiene tiempos de búsqueda rápidos.
El ejemplo email tiene tres páginas con formularios HTML, dos ficheros de respuesta,
una página de error, y un componente JavaBean. Podemos visualizar la estructura de
ficheros en algo como esto:
<html>
<head><title>Email Finder</title></head>
<body bgcolor="#ffffff" background="background.gif" link="#000099">
<form method="get">
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<td width="120"> </td>
<td align="right"> <h1>Email Finder</h1> </td>
</tr>
<tr>
<td width="120" align="right"><b>Name</b></td>
<td align="left"><input type="text" name="name" size="35"></td>
</tr>
<tr>
<td width="120" align="right"><b>Email Address</b></td>
<td align="left"><input type="text" name="email" size="35"></td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
Please enter a name and an email address.
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<input type="submit" value="Add">
</td>
</tr>
<%
String rname = request.getParameter( "name" );
String remail = request.getParameter( "email" );
if ( rname != null) {
mymap.put( rname, remail );
}
%>
<tr>
<td width="120"> </td>
<td align="right">
The map file has <font color="blue"><%= mymap.size() %>
</font> entries.
</font>
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<a href="lookup.jsp">Lookup</a> |
<a href="delete.jsp">Delete</a>
</td>
</tr>
</table>
</form>
</body>
</html>
<form method="get">
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<td width="120"> </td>
<td align="right"> <h1>Email Finder</h1> </td>
</tr>
<tr>
<td width="120" align="right"><b>Name</b></td>
<td align="left"><input type="text" name="name" size="35"></td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
Please enter a name for which
<br>
you'd like an email address.
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
The map file has <font color="blue"> <%= mymap.size() %></font>
entries.
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right"> <input type="submit" value="Lookup"> </td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<a href="email.jsp">Add</a> |
<a href="delete.jsp">Delete</a>
</td>
</tr>
</table>
</body>
</html>
<tr>
<td width="120"> </td>
<td align="right">
<b> Success! </b>
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<jsp:getProperty name="mymap" property="name" />
<br>
<jsp:getProperty name="mymap" property="email" />
</td>
</tr>
<html>
<head><title> Email Finder </title></head>
<body bgcolor="#ffffff" background="background.gif" link="#000099">
<form method="get">
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<td width="120"> </td>
<td align="right"> <h1>Email Finder</h1> </td>
</tr>
<tr>
<td width="120" align="right"><b>Name</b></td>
<td align="left"> <input type="text" name="name" size="35"> </td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
Please enter a name you would like to delete.
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
The map file has <font color="blue"> <%= mymap.size() %></font>
entries.
</td>
</tr>
<tr>
<td width="120"> </td>
<td align="right"> <input type="submit" value="Delete"> </td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<a href="email.jsp">Add</a> |
<a href="lookup.jsp">Lookup</a>
</td>
</tr>
</table>
</body>
</html>
<tr>
<td width="120"> </td>
<td align="right"> <b>Success!</b> </td>
</tr>
<tr>
<td width="120"> </td>
<td align="right">
<jsp:getProperty name="mymap" property="name" />
<br>
<jsp:getProperty name="mymap" property="email" />
<br><p>
has been deleted from the map file.
</td>
</tr>
<html>
<head><title>Email Finder</title></head>
<body bgcolor="#ffffff" background="background.gif" link="#000099">
<tr>
<td width="150" align="right"> </td>
<td align="right"> <b>Oops! an exception occurred.</b> </td>
</tr>
<tr>
<td width="150" align="right"> </td>
<td align="right">The name of the exception is
<%= exception.toString() %>.
</td>
</tr>
<tr>
<td width="150" align="right"> </td>
<td align="right"> </td>
</tr>
<% }
<% }
else if (mymap.getAction() == "add" ) { %>
<tr>
<td width="150" align="right"> </td>
<td align="right">
<b><i>This means that ...</b></i>
<p>You were trying to <font color="blue">add</font>
an entry with a name of null.
<br>
The map file doesn't allow this.
<p>
Want to try <a href="email.jsp">again</a>?
</td>
</tr>
<% } %>
</table>
package email;
import java.util.*;
public Map() { }
En este ejemplo, el código que lanza excepciones es la clase TreeMap, que extiende
nuestro email.Map, por eso no tenemos que escribir código que lance excepciones en
el Bean.
Los métodos que hemos usado de TreeMap son estos con sus excepciones:
● public Object get( Object key ) throws ClassCastException,
NullPointerException- recupera una entrada de un fichero map.
● public Object put( Object key, Object value ) throws ClassCastException,
NullPointerException-añade una entrada al fichero map.
● public Object remove( Object key ) throws ClassCastException,
NullPointerException- elimina una entrada del fichero map.
● int size() - devuelve el número de entradas del fichero map.
El primer caso, cuando el usuario intenta añadir un nombre o dirección de email nulos,
es manejado por un sencillo código en el Bean y en email.jsp. (Aquí null significa que
el usuario no ha introducido nada en la caja de texto del formulario. No maneja el
caso en que el usuario teclee uno o dos espacio en blanco, y luego pulsa Return).
El código que maneja la adicción de valores null está en los métodos setName y
setEmail de Map.java y en un scriptlet en email.jsp:
Capturar un Valor Null Durante la Adicción
Map.java:
email.jsp:
<%
String rname = request.getParameter( "name" );
String remail = request.getParameter( "email" );
if ( rname != null) {
mymap.put( rname, remail );
}
%>
Tanto setName como setEmail chequean su el usuario ha introducido un valor en el
formulario antes de seleccionar sus respectivas propiedades. Si el formulario es un
valor null, el Bean no selecciona ninguna propiedad, el método put no añade nada al
fichero map, y no se lanza ninguna excepción.
Cuando el Usuario Intenta Buscar un Valor Null
Pero si vamos a las páginas Lookup o Delete del ejemplo e intentamos buscar o borrar
una entrada que no está en el fichero map, la aplicación email lanza una
NullPointerException y muestra una página de error.
Capturar un Valor Null durante la Búsqueda
lookup.jsp:
lookupresponse.jsp:
<tr>
<td width="120"> </td>
<td align="right">
<font face="helvetica" size="-2">
<jsp:getProperty name="mymap" property="name" />
<br>
<jsp:getProperty name="mymap" property="email" />
</font>
</td>
</tr>
Este ejemplo tiene dos piezas de código que trabajan juntas. La página lookup.jsp,
donde introducimos un nombre por el que queremos buscar en el fichero map, tiene
un scriptlet que chequea si el usuario ha introducido un nombre en el formulario o no.
Si el usuario no ha introducido un nombre o introduce uno que no existe en el fichero
map, el Bean lanza una NullPointerException y la aplicación muestra una página de
error -- que es el comportamiento deseado! En este caso, podemos estar felices
porque se muestra la página de error.
Podríamos haber observado que las líneas del fichero lookupresponse.jsp usan la
etiqueta <jsp:getProperty> para recuperar el nombre y la dirección email desde el
Bean. También podríamos intentar recuperar la dirección email usando expresiones,
algo como esto:
delete.jsp:
deleteresponse.jsp:
<tr>
<td width="120"> </td>
<td align="right">
<font face="helvetica" size="-2">
<jsp:getProperty name="mymap" property="name" />
<br>
<jsp:getProperty name="mymap" property="email" />
<br><p>
has been deleted from the map file.
</font>
</td>
</tr>
Para hacer que las páginas muestren una página de error, cada página de la aplicación
email usa una directiva page con el atributo errorPage, de esta forma:
Una página de error es diferente a una página normal JSP. En una página de error,
debemos seleccionar explícitamente el atributo isErrorPage de la directiva page
como true. También tendremos acceso al objeto exception, que nos dará
información sobre la excepción.
Primero, veamos un ejemplo de la directiva page de una página de error:
El ejemplo email usa una propiedad llamada action en Map.java para seguir la
página en la que el usuario estaba trabajando cuando se lanzó la excepción. Esto nos
da información importante para ayudarnos a escribir un mensaje de error informativo
para el usuario. El Bean tiene una variable llamada action, un método getAction, y
un método setAction. La declaraciones de variable y métodos en el Bean se parecen
a esto:
Para poder ejecutar este ejemplo, necesitamos tener instalado el JDK 1.2 (si no lo
tienes, puedes ir a http://java.sun.com/products/OV_jdkProduct.html.)
Los paths dados aquí son para un sistema UNIX, si estás usando Windows, deberás
usar los mismos paths pero con el separador de directorios invertido:
1. Creamos el directorio (o carpeta)
../jswdk-1.0/examples/jsp/tutorial/email.
2. Situamos los siguientes ficheros en el directorio ../tutorial/email:
background.gif, delete.jsp, deleteresponse.jsp, email.jsp, error.jsp,
lookup.jsp, lookupresponse.jsp.
3. Creamos el directorio (o carpeta)
../jswdk-1.0/examples/WEB-INF/jsp/beans/email.
4. Situamos los ficheros Map.class y Map.java en el directorio ../beans/email.
5. Arrancamos la implementación de referencia JSP de Sun:cd
../jswdk-1.0startserver
6. Abrimos un navegador Web y vamos a:
http://yourMachineName:8080/examples/jsp/
tutorial/email/email.jsp
Ozito