You are on page 1of 50

4.

1 Tutorial de servlets
Introducción (1)
„ Un servlet es una clase Java que puede recibir
peticiones (normalmente HTTP) y generar una salida
(normalmente HTML, WML o XML)
„ Los servlets que conforman una aplicación web se
ejecutan en un servidor de aplicaciones web
(contenedor)
„ Cada servlet se puede asociar a una o más URLs
„ Paquetes javax.servlet y
javax.servlet.http
Introducción (y 2)
„ Hasta la aparición de JSP, el uso principal de los
servlets era generar la vista de una aplicación web
„ Recibir petición HTTP asociada a una URL
„ Leer parámetros
„ Invocar operación sobre el modelo
„ Generar salida HTML
„ Motivos para aprender servlets
„ Para usar JSP y Struts es preciso conocer parte del API de
los servlets, dado que aunque JSP y Struts están en un nivel
superior, no ocultan el API de los servlets
„ Son útiles para implementar el controlador de una aplicación
web
„ Apache Struts proporciona un servlet genérico que constituye
la parte principal del controlador
Visión global del framework de servlets (1)
<<interface>>
javax.servlet.Servlet

+ init(config : ServletConfig) : void


+ destroy() : void
+ service(request : ServletRequest, response : ServletResponse) : void

javax.servlet.GenericServlet

+ init(config : ServletConfig) : void


+ destroy() : void
+ service(request : ServletRequest, response : ServletResponse) : void

javax.servlet.http.HttpServlet

+ service(request : ServletRequest, response : ServletResponse) : void


# service(request : HttpServletRequest, response : HttpServletResponse) : void
# doGet(request : HttpServletRequest, response : HttpServletResponse) : void
# doPost(request : HttpServletRequest, response : HttpServletResponse) : void
Visión global del framework de servlets (2)

<<interface>> <<interface>>
javax.servlet.ServletRequest javax.servlet.ServletResponse

+ getParameter(name : String ) : String + setContentType(type : String ) : void


+ getParameterValues(name : String) : String[] + getWriter () : java.io.PrintWriter

<<interface>> <<interface>>
javax.servlet.http.HttpServletRequest javax.servlet.http.HttpServletResponse
Visión global del framework de servlets (3)

„ El diagrama UML anterior sólo ofrece una visión muy


reducida del API de servlets, pero suficiente en este
momento
„ Cuando el servidor de aplicaciones web decide cargar
un servlet en memoria (ej.: al arrancar, la primera
vez que se accede a él) llama a la operación init de
javax.servlet.Servlet
„ Cuando el servidor de aplicaciones web decide
eliminar un servlet de memoria (ej.: lleva cierto
tiempo sin usarse), llama a la operación destroy de
javax.servlet.Servlet
Visión global del framework de servlets (4)

„ La operación pública service de


javax.servlet.http.HttpServlet llama a la
operación protegida service
„ Esta operación es una operación plantilla (Template
Method), que llama a doGet, doPost, doPut, doDelete,
etc., según la petición HTTP sea un GET, POST, PUT,
DELETE, etc.
„ Normalmente, el programador extiende de
javax.servlet.http.HttpServlet y redefine
doGet y/o doPost
Visión global del framework de servlets (5)

„ En una máquina virtual Java, sólo existe una


instancia de cada servlet que se programe, y en
consecuencia puede recibir peticiones concurrentes
„ doGet, doPost, etc. deben ser thread-safe
„ Normalmente no será necesario hacer nada especial, dado
que la implementación de estas operaciones generalmente
sólo hace uso de variables locales (pila) o de variables
globales (static) de sólo lectura (típicamente caches)
„ Si modifican alguna estructura global (un atributo propio o
alguna variable global), necesitan sincronizar su acceso
„ Sin embargo, en general, eso es mala idea, dado que una
aplicación con estas características no será fácil que funcione
en un entorno en cluster
„ En estos casos, es mejor usar una base de datos para las
estructuras globales que sean de lectura/escritura
Visión global del framework de servlets (y 6)

„ javax.servlet.http.HttpServletRequest
„ getParameter
Permite obtener el valor de un parámetro univaluado
„ getParameterValues
„ Permite obtener el valor de un parámetro multivaluado
„ También se puede usar con parámetros univaluados
„ IMPORTANTE: cuando el usuario no selecciona ningún valor
(ej.: en una lista desplegable múltiple o una lista de
checkboxes en HTML), el navegador no envía el parámetro, y
en consecuencia, esta operación devuelve null
„ javax.servlet.http.HttpServletResponse
„ setContentType debe llamarse antes de escribir en el
PrintWriter que devuelve getWriter
Página principal del tutorial
Index.jsp
<html>

...

<ul>
<li><a href="Hello1/HelloUser?userName=Fernando+Bellas">
HelloUser by GET (userName = Fernando Bellas)</a></li>
<li><a href="Hello1/HelloUserByPost.html">HelloUser by POST</a></li>
<li><a href="Portal1/MainPage">Portal-1 main page</a></li>
</ul>

...

</html>
Portal1/HelloUserByPost.html
<html>
...
<form method="POST" action="HelloUser">
<table width="100%" border="0" align="center" cellspacing="12">

<tr>
<th align="right" width="50%">User name</th>
<td align="left">
<input type="text" name="userName" size="16“
maxlength="16">
</td>
</tr>

<tr>
<td width="50%“></td>
<td align="left" width="50%">
<input type="submit" value="Say me hello">
</td>
</tr>
</table>
</form>
...
</html>
Demo HelloUser (1)

Servlet and JSP Tutorial Main Page

Clic en HelloUser by GET (userName = Fernando Bellas)


Demo HelloUser (y 2)
Servlet and JSP Tutorial Main Page

Clic en HelloUser by POST


es.udc.fbellas.j2ee.servjsptutorial.hellouser1.HelloUserServlet (1)

package es.udc.fbellas.j2ee.servjsptutorial.hellouser1;

import java.io.PrintWriter;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloUserServlet extends HttpServlet {

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

/* Get value of parameter "userName". */


String userName = request.getParameter("userName");

/* Generate response. */
response.setContentType("text/html; charset=ISO-8859-1");
es.udc.fbellas.j2ee.servjsptutorial.hellouser1.HelloUserServlet (y 2)

PrintWriter out = response.getWriter();

out.println("<html><head><title>");
out.println("HelloUser response");
out.println("</title></head>");
out.println("<body text=\"#000000\" bgcolor=\"#ffffff\">");
out.println("<h1>Hello " + userName + "! </h1>");
out.println("</body></html>");

out.close();

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

doGet(request, response);

}
Empaquetamiento de una aplicación web (1)

„ Una aplicación web se empaqueta en un fichero


.war
„ jar cvf aplicacionWeb.war directorio
„ Opciones similares al comando Unix tar
„ El nombre de una aplicación web no tiene porque coincidir
con el de su fichero .war
„ El nombre se decide al instalar el fichero .war
„ Ant incluye la tarea interna war
„ Estructura de un fichero .war
„ Directorio WEB-INF/classes
„ Ficheros .class que conforman la aplicación web, agrupados
en directorios según su estructura en paquetes
„ ¡ Sin ficheros fuente !
„ Directorio WEB-INF/lib
„ Ficheros .jar de librerías que usa la aplicación
„ ¡ Sin ficheros fuente !
Empaquetamiento de una aplicación web (2)

„ Estructura de un fichero .war (cont)


„ WEB-INF/web.xml
„ Configuración estándar de la aplicación web
„ Si la aplicación necesita otros ficheros de configuración (ej.:
ficheros de configuración de Struts, ficheros de configuración
propios, etc.), se recomienda incluirlos debajo de WEB-INF
(seguramente en subdirectorios)
„ Directorio raíz y subdirectorios
„ Vista de la aplicación (ej.: ficheros HTML, páginas JSP,
imágenes, etc.)
„ Visible a los navegadores
„ Lo que hay debajo de WEB-INF sólo es visible a los servlets y
páginas JSP de la aplicación
„ Un fichero .war se puede instalar (deployment) en
cualquier servidor de aplicaciones web conforme a
J2EE
Empaquetamiento de una aplicación web (y 3)

„ Un contenedor de aplicaciones web usa un cargador


de clases distinto para cada war instalado =>
independencia entre aplicaciones web
„ Distintas aplicaciones web pueden usar versiones distintas
de una misma clase
„ Dos aplicaciones web nunca podrán compartir una variable
global
„ Existe una instancia de un Singleton por cada aplicación que lo
use
„ Ej.: Considerar el atributo estático (variable global)
parameters de ConfigurationParametersManager
„ Si dos aplicaciones web usan esta clase, el contenedor cargará
una clase por cada aplicación, y en consecuencia parameters
tendrá un valor distinto en cada aplicación
„ Es lo que deseamos, dado que en general, la configuración será
distinta
jar tvf ServJSPTutorial.war (1)

Portal2/MainPage.jsp
Portal2/ShowLogin.jsp
Portal2/ProcessLogin.jsp
Portal2/ProcessLogout.jsp
Hello2/HelloUserByPost.html
Hello2/HelloUser.jsp
Hello1/HelloUserByPost.html
Index.jsp
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal1/
ShowLoginServlet.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal1/
MainPageServlet.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal1/
LoginManager.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal1/
ProcessLoginServlet.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal1/
ProcessLogoutServlet.class
jar tvf ServJSPTutorial.war (y 2)

WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal2/
LoginManager.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal2/
IncorrectPasswordException.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/portal2/
LoginForm.class
WEB-INF/classes/es/udc/fbellas/j2ee/servjsptutorial/hellouser1/
HelloUserServlet.class
WEB-INF/web.xml
WEB-INF/web.xml (1)
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<distributable/>

<!-- ===================== Servlets ============================= -->

<servlet>
<servlet-name>HelloUser</servlet-name>
<servlet-class>es.udc.fbellas.j2ee.servjsptutorial.hellouser1.
HelloUserServlet</servlet-class>
</servlet>

... Resto de servlets del tutorial ...


WEB-INF/web.xml (y 2)
<!-- ==================== Servlet mapping ======================= -->

<servlet-mapping>
<servlet-name>HelloUser</servlet-name>
<url-pattern>/Hello1/HelloUser</url-pattern>
</servlet-mapping>

... Mappings para el resto de servlets del tutorial ...

<!-- ========================= Session =========================== -->

<session-config>
<session-timeout>30</session-timeout>
</session-config>

<!-- ======================= Welcome page ======================== -->

<welcome-file-list>
<welcome-file>Index.jsp</welcome-file>
</welcome-file-list>

</web-app>
Comentarios (1)
„ Desde la versión 2.4 de la especificación de servlets,
los tags que se pueden usar dentro del fichero
web.xml están especificados en un esquema
(anteriormente lo estaban en un DTD)
„ Espacios de nombres
„ Concepto similar al de paquete en Java
„ Permiten evitar conflictos de nombres cuando en un
documento XML se usan tags de distintas aplicaciones XML
„ Cada espacio de nombres está asociado a una URI, que
debe ser única
„ Se aconseja usar URLs
„ No tienen porque tener una existencia real (y de hecho, no
suelen tenerla)
Comentarios (2)
„ En el fichero web.xml se usa
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
„ xmlns="http://java.sun.com/xml/ns/j2ee" permite
especificar que el elemento web-app y los que éste contiene
pertenecen al espacio de nombres definido por la URI
http://java.sun.com/xml/ns/j2ee
„ “Similar a package”
„ xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" permite especificar que el elemento web-app y los
que éste contiene pueden usar los atributos y elementos del
espacio de nombres asociado con la URI
http://www.w3.org/2001/XMLSchema-instance,
prefijándolos con xsi:
„ “Similar a import”
„ Es la URI la que define el espacio de nombres y no el prefijo
„ Distintas documentos XML pueden usar distintos prefijos para referirse a un
mismo espacio de nombres
Comentarios (3)
„ En el fichero web.xml se usa (cont)
„ El atributo xsi:schemaLocation permite especificar las
ubicaciones de los esquemas asociados a un conjunto de
espacios de nombres
„ Contiene una lista de pares de valores separados por blancos
(xsi:schemaLocation="en1 ue1 ... enN ueN")
„ El primer miembro especifica un espacio de nombres (en)
„ El segundo miembro especifica la ubicación del esquema (ue)
que define los elementos y atributos de ese esquema
„ El procesador del documento XML no está obligado a hacer uso
de las ubicaciones especificadas (e.g. puede tener copias
locales de los esquemas)
„ Cualquier procesador tiene una copia del esquema
correspondiente al espacio de nombres
http://www.w3.org/2001/XMLSchema-instance, y por eso
no se especifica en xsi:schemaLocation
„ Cualquier contenedor de aplicaciones web J2EE posiblemente
tendrá una copia del esquema correspondiente al espacio de
nombres http://java.sun.com/xml/ns/j2ee
Comentarios (y 4)
„ El anterior fichero web.xml sólo muestra algunos
tags típicos
„ Existe un gran número de tags (la mayoría opcionales) que
permiten expresar muchas opciones de configuración
„ Iremos viendo ejemplos de los tags más típicos a medida
que nos hagan faltan
„ distributable
„ La aplicación puede funcionar en cluster
„ Nuestras aplicaciones siempre deberían estar diseñadas e
implementadas para que puedan funcionar en cluster
„ Los servidores de aplicaciones comerciales suelen
generar el fichero web.xml automáticamente
„ El usuario utiliza un cómodo wizard para especificar la
información de configuración
Tipos de URLs en HTML (1)

„ Las URLs que muestran las imágenes del navegador


empiezan por http://localhost:8080/ServJSPTutorial
„ Son URLs absolutas
„ localhost:8080: máquina y puerto en el que corre el
servidor de aplicaciones (en este caso Tomcat)
„ /ServJSPTutorial: nombre de la aplicación web
„ En un servidor de aplicaciones pueden instalarse varias
aplicaciones web
„ Las URLs que se usan en los ficheros HTML o en las
respuestas generadas del ejemplo son de tipo path
relativo, y en consecuencia no incluyen
http://localhost:8080/ServJSPTutorial
„ Buena idea, permite instalar la aplicación en otro servidor
bajo un nombre distinto
Tipos URLs en HTML (y 2)

„ Si se desea escribir una URL de tipo path absoluto en


un fichero HTML o una respuesta generada, ésta ha
de empezar por /nombreAplicación
<a href=“/ServJSPTutorial/Hello1/HelloUser?
userName=Fernando+Bellas”>
HelloUser by GET userName = Fernando Bellas</a>

„ Es posible generar automáticamente la parte del nombre de


la aplicación
„ Permite instalar la aplicación con otro nombre, sin que haya
que modificar ningún servlet
„ request.getContextPath() devuelve
/nombreAplicación
„ Volveremos a hablar sobre tipos de URLs en el
siguiente ejemplo (Portal-1)
Demo Portal-1 (1)
Servlet and JSP Tutorial Main Page

Clic en Portal-1 main page


Demo Portal-1 (2)
Demo Portal-1 (y 3)

Clic en Servlet and JSP tutorial main page Clic en Logout

Servlet and JSP Tutorial Main Page Servlet and JSP Tutorial Main Page

Clic en Portal-1 main page Clic en Portal-1 main page

Portal-1 login form


es.udc.fbellas.j2ee.servjsptutorial.portal1

HttpS ervlet
(fro m h ttp )

M ainP ageS ervlet S howLoginS ervlet P rocess LoginS ervlet P roc es sLogoutS ervlet

< < us e> > < < us e >>


< < us e> >

Log inM anager

- Logi nMana ger()


< < static >> + login(reques t : Ht tpS ervl etReques t, l oginNam e : S tring) : void
< < s tatic> > + logout(request : HttpS ervletRequest) : void
< < s tatic> > + getLoginNam e(request : HttpS ervletRequest) : S tring
Concepto de sesión (1)
„ El API de servlets permite crear una sesión en el servidor por
cada navegador que accede a una aplicación web
„ Cada navegador dispone de su propio objeto
javax.servlet.http.HttpSession en el servidor
„ Es posible enganchar objetos a una sesión y recuperarlos
„ void setAttribute(String, Object)
„ Object getAttribute(String)
„ Por motivos de escalabilidad y de que en HTTP no hay nada
especial que indique que un navegador ha dejado de usar la
aplicación web, cada sesión dispone de un timeout (en minutos)
„ Si transcurre el timeout sin que el navegador acceda a la
aplicación, el servidor destruye la sesión
„ Configurable en web.xml
Concepto de sesión (2)
„ En el ejemplo
„ Cada vez que un usuario hace un login, crearemos una
sesión, le engancharemos su nombre de login, y lo
redirigiremos a la página principal del portal
„ Cada vez que el usuario accede a la página principal del
portal, si ya ha hecho el login, se le saludará por su nombre
(se recupera de la sesión)
„ Cada vez que el usuario accede a la página principal del
portal, si todavía no ha hecho el login, o su sesión ha
caducado, se le redirigirá a la página de login
„ Cuando un usuario hace un logout, le destruiremos la sesión
y lo redirigiremos a la página principal del tutorial
Concepto de sesión (y 3)
„ ¿ Qué ocurre cuando el servidor de aplicaciones web
se ejecuta en un cluster (distributable) ?
„ El servidor garantiza que todas las peticiones que sean parte
de una sesión serán procesadas por una máquina virtual
„ Los objetos de la sesión tienen que ser serializables
„ El servidor de aplicaciones puede decidir moverlos a otra
máquina por motivos de escalabilidad y/o tolerancia a fallos
„ En realidad, el concepto de sesión tiene más matices
„ HTTP es un protocolo sin estado
„ ¿ Cómo sabe el servidor de aplicaciones a qué sesión está
asociada cada petición HTTP que recibe ?
„ Mecanismos: típicamente cookies o URL rewriting
„ Los estudiaremos en el siguiente apartado
es.udc.fbellas.j2ee.servjsptutorial.portal1.MainPageServlet (1)

public class MainPageServlet extends HttpServlet {

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

String loginName = LoginManager.getLoginName(request);

if (loginName != null) { // User has already logged in.


generateMainPage(response, loginName);
} else { // User has not logged in yet.
response.sendRedirect("ShowLogin");
}

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

doGet(request, response);

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.MainPageServlet (y 2)

private void generateMainPage(HttpServletResponse response,


String loginName) throws IOException {

response.setContentType("text/html; charset=ISO-8859-1");
PrintWriter out = response.getWriter();

out.println("<html><head><title>");
out.println("Portal-1 main page");
out.println("</title></head>");
out.println("<body text=\"#000000\" bgcolor=\"#ffffff\" " +
"link=\"#000ee0\" vlink=\"#551a8b\" alink=\"#000ee0\">");
out.println("<h1>Hello " + loginName + "! </h1>");
out.println("<br><br><br>");
out.println("<a href=\"../Index.jsp\">Servlet and JSP tutorial " +
"main page</a><br>");
out.println("<a href=\"ProcessLogout\">Logout</a><br>");
out.println("</body></html>");

out.close();

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.ShowLoginServlet (1)

public class ShowLoginServlet extends HttpServlet {

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

/* Get values to show. */


Map errors = (Map) request.getAttribute("errors");
String loginName = "";
String loginNameErrorMessage = "";

if (errors != null) {

String errorHeader = "<font color=\"red\"><b>";


String errorFooter = "</b></font>";

if (errors.containsKey("loginName")) {
loginName = request.getParameter("loginName");
loginNameErrorMessage = errorHeader +
errors.get("loginName") + errorFooter;
}

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.ShowLoginServlet (2)

/* Generate response. */
response.setContentType("text/html; charset=ISO-8859-1");
PrintWriter out = response.getWriter();

/* Header and begin of body. */


out.println("<html><head><title>");
out.println("Portal-1 login form");
out.println("</title></head>");
out.println("<body text=\"#000000\" bgcolor=\"#ffffff\">");

/* Begin of form. */
out.println("<form method=\"POST\" action=\"ProcessLogin\">");

/* Begin of table. */
out.println("<table width=\"100%\" border=\"0\" align=\"center\" " +
"cellspacing=\"12\">");
es.udc.fbellas.j2ee.servjsptutorial.portal1.ShowLoginServlet (3)

/* Login name. */
out.println("<tr>");

out.println("<th align=\"right\" width=\"50%\"> Login name </th>");


out.println("<td align=\"left\">" +
"<input type=\"text\" name=\"loginName\" " +
" value=\"" + loginName + "\" size=\"16\" maxlength=\"16\">" +
loginNameErrorMessage + "</td>");

out.println("</tr>");

/* Print Login button. */

out.println("<tr>");

out.println("<td width=\"50%\"></td>");
out.println("<td align=\"left\" width=\"50%\"> " +
"<input type=\"submit\" value=\"Login\"></td>");

out.println("</tr>");
es.udc.fbellas.j2ee.servjsptutorial.portal1.ShowLoginServlet (y 4)

/* End of table. */
out.println("</table>");

/* End of body and html. */


out.println("</body></html>");

/* Close "out". */
out.close();

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {
doGet(request, response);
}

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.ProcessLoginServlet (1)

public class ProcessLoginServlet extends HttpServlet {

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

String loginName = request.getParameter("loginName");

if ( (loginName == null) || (loginName.trim().length() == 0) ) {

Map errors = new HashMap();


errors.put("loginName", "Mandatory field");
request.setAttribute("errors", errors);

forwardToShowLogin(request, response);

} else {
LoginManager.login(request, loginName.trim());
response.sendRedirect("MainPage");
}

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.ProcessLoginServlet (y 2)

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

doPost(request, response);

private void forwardToShowLogin(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/Portal1/ShowLogin");

requestDispatcher.forward(request, response);

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.ProcessLogoutServlet

public class ProcessLogoutServlet extends HttpServlet {

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

LoginManager.logout(request);
response.sendRedirect("../Index.jsp");

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

doGet(request, response);

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.LoginManager (1)
public final class LoginManager {

private final static String LOGIN_NAME_SESSION_ATTRIBUTE =


"loginName";

private LoginManager() {}

public final static void login(HttpServletRequest request,


String loginName) {

HttpSession session = request.getSession(true);

session.setAttribute(LOGIN_NAME_SESSION_ATTRIBUTE, loginName);

public final static void logout(HttpServletRequest request) {

HttpSession session = request.getSession(false);

if (session != null) {
session.invalidate();
}

}
es.udc.fbellas.j2ee.servjsptutorial.portal1.LoginManager (y 2)

public final static String getLoginName(HttpServletRequest request) {

HttpSession session = request.getSession(false);

if (session == null) {
return null;
} else {
return (String) session.getAttribute(
LOGIN_NAME_SESSION_ATTRIBUTE);
}

}
Comentarios (1)
„ El ejemplo, aparte de ilustrar el uso de sesiones,
hace énfasis en el uso de sendRedirect y
forward
„ sendRedirect
„ Le decimos al navegador que nos haga una nueva petición a
otra URL
„ forward
„ Nos movemos a otra URL
„ Ocurre dentro del servidor
„ Se conserva todo lo que había en la request
„ Útil para tratar errores en formularios
„ Los servlets de procesamiento enganchan el atributo errors
(un Map) en la request
„ Los servlets que muestran formularios comprueban si la
request incluye el atributo errors
Comentarios (2)
„ Más sobre tipos de URLs
„ Los tipos de URLs que hemos visto al principio de este
apartado se refieren a las URLs en ficheros HTML, páginas
JSP o respuestas generadas
„ ¿ Qué tipos de URLs acepta sendRedirect ?
„ Los tres tipos que conocemos hasta ahora
„ Lógico, pues un sendRedirect se usa para informar al
navegador que nos haga una petición a otra URL
„ ¿ Qué tipos de URLs acepta forward ?
„ De tipo path relativo (sin salir de la aplicación)
„ De tipo path relativo a contexto
„ Empiezan por “/” y no incluyen el nombre de la aplicación
„ Ej.: /Portal1/MainPage
„ Existe otra manera de hacer forwards distinta a la mostrada
en el ejemplo, que sólo acepta URLs de tipo path relativo a
contexto
„ Servlet.getServletContext().getRequestDispatcher
(String)
Comentarios (y 3)
„ ¿ Cuándo usar forward y cuándo sendRedirect ?
„ En principio, un forward siempre es más rápido (ocurre en
el servidor)
„ Un forward es preciso cuando queremos enganchar
atributos a la request
„ Ej.: Tratamiento de errores en formularios
„ Para el resto de situaciones, es mejor usar un
sendRedirect, dado que forward no cambia la URL que
muestra la caja de diálogo del navegador (el navegador no
se entera de que se hace un forward), lo que será confuso
si el usuario decide recargar la página (se invocará a la URL
antigua que todavía muestra la caja de diálogo del
navegador)