Está en la página 1de 63

4.

4 Tutorial de Jakarta Struts


¿ Qué es Struts ?
n Framework OpenSource para implementar
aplicaciones web con servlets y JSP según el patrón
arquitectónico Model-View-Controller
n Subproyecto de Jakarta
n Autor principal: Craig R. McClanahan
n Funciona sobre cualquier servidor de aplicaciones
web que implemente las APIs de servlets y JSP
n Julio 2001: versión 1.0
n Ha ganado gran relevancia en el mundo de las
aplicaciones web Java
n Paquetizado en un fichero .jar
¿ Qué proporciona Struts ?
n Un servlet Front Controller y clases relacionadas
n Un gran número de acciones JSP
n View Helpers
n La mayor parte de las que se necesitan en una situación real
n Un pool genérico de conexiones a una BD relacional
n Implementa javax.sql.DataSource
El patrón Front Controller en Struts (1)

javax.servlet.http.HttpServlet

org.apache.struts.action.ActionServlet org.apache.struts.action.Action
0..n
# doGet + perform
# doPost

<<use>> <<instantiate>>

org.apache.struts.action.ActionForm

+ reset Action1 ActionN


+ validate ...

ActionForm1 ActionFormN
... <<use>>
El patrón Front Controller en Struts (2)
n ActionServlet
n Servlet Front Controller
n En web.xml se especifica que todas las URLs que impliquen
procesamiento (por GET o POST) vayan a este servlet
n Ej.: las URLs que termine en .do
n Clases ActionForm
n Si el programador lo desea, puede acceder a los parámetros de la
request a través de un JavaBean que extiende ActionForm
n Especialmente útil en formularios
n Clase Action => método perform
n Accede a los parámetros de la request, directamente o vía el
ActionForm correspondiente
n Realiza la operación invocando un método de un Session
Facade del modelo o una fachada del controlador
n Deja el resultado devuelto por el método en la request o en la
sesión
n Devuelve un objeto ActionForward, que representa la URL que
hay que visualizar a continuación (sendRedirect o forward)
El patrón Front Controller en Struts (3)
n Fichero de configuración
n Clases ActionForm que usa nuestra aplicación
n Nombre lógico (ej.: loginForm)
n Nombre completo de la clase (ej.:
es.udc.fbellas.j2ee.strutstutorial.portal3.http
.view.actionforms.LoginForm)
n URLs que implican procesamiento
n URL de tipo path relativo a contexto (ej.: /Login)
n No llevan el .do final
n Nombre completo de la clase Action (ej.:
es.udc.fbellas.j2ee.strutstutorial.portal3.http
.controller.actions.LoginAction)
n Nombre lógico de la clase ActionForm asociada
El patrón Front Controller en Struts (y 4)

n Fichero de configuración (cont)


n Definiciones de nombres lógicos de URLs
n Nombre que usan las acciones cuando devuelven un
ActionForward (ej.: ShowMainPage)
n sendRedirect o forward
n URL a invocar (ej.: /MainPage.jsp)
n Cuando el servlet ActionServlet arranca (init), lee el
fichero de configuración
n Crea una única instancia de cada clase Action
n No se crea una instancia de una clase Action por cada
petición que se recibe
n Tienen que ser thread-safe
n Misma situación que cuando se trabaja con servlets
Acciones JSP

n Bean
n Imprimir el valor de las propiedades de JavaBeans de
manera segura
n Soporte para internacionalización de mensajes
n HTML
n Generación de HTML básico
n Campos de entrada en formularios
n Enlaces (con URL rewriting)
n Logic
n Si mayor que, si menor que, etc.
n Iteración sobre colecciones de objetos
n Template
n Caso particular del patrón Composite View
n Lo veremos con MiniBank y MiniPortal
Arquitectura MVC con Struts
n Modelo
n Clases independientes de la vista y el controlador
n Controlador
n Quizás se necesite extender el servlet ActionServlet
n Conjunto de clases Action
n Interactúan con el modelo y seleccionan la siguiente vista
(dejándole los datos en uno de los cuatro posibles ámbitos,
normalmente request o session)
n Vista
n Conjunto de clases ActionForm
n Conjunto de páginas JSP
n No contienen código Java
n Sólo visualizan datos
n Usan acciones JSP (las de Struts, las estándares y quizás
algunas desarrolladas a medida) para recuperar los valores a
mostrar y formatearlos
Demo Portal-3 (1)
Lanzar el navegador

Acceder a Portal-3 main page


Demo Portal-3 (2)

Clic Login
Demo Portal-3 (y 3)

Clic en Logout
Terminar y lanzar el navegador dos días más tarde

Acceder a Portal-3 main page Portal-3 main page


(Welcome to Portal-3)
Estructura de paquetes
es.udc.fbellas.j2ee.util.struts.action

es.udc.fbellas.j2ee.strutstutorial.portal3

http

controller

actions

view

actionforms
messages

model

userfacade

delegate
exceptions
tar tvf StrutsTutorial.war (1)
MainPage.jsp
InternalError.jsp
Login.jsp
Index.jsp
WEB-INF/Struts/struts-bean.tld
WEB-INF/Struts/struts-html.tld
WEB-INF/Struts/struts-logic.tld
WEB-INF/Struts/struts-config.xml
WEB-INF/lib/struts.jar
WEB-INF/lib/crimson.jar
WEB-INF/lib/jaxp.jar
WEB-INF/lib/StandardUtil.jar
WEB-INF/lib/WebUtil.jar
tar tvf StrutsTutorial.war (y 2)
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/model/
userfacade/delegate/UserFacadeDelegate.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/model/
userfacade/exceptions/IncorrectPasswordException.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/
controller/actions/LoginManager.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/
controller/actions/LogoutAction.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/
controller/actions/LoginAction.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/
controller/actions/MainPageAction.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/view/
actionforms/LoginForm.class
WEB-INF/classes/es/udc/fbellas/j2ee/strutstutorial/portal3/http/view/
messages/Messages.properties
WEB-INF/web.xml
Comentarios
n WEB-INF/Struts
n Ficheros *.tld: descriptores de las librerías de las acciones
proporcionadas por Struts
n struts-config.xml: configuración de Struts para la
aplicación del tutorial
n WEB-INF/lib
n struts.jar: ficheros .class de Struts
n crimson.jar y jaxp.jar: Struts usa JAXP para parsear

el fichero struts-config.xml
n StandarUtil.jar y WebUtil.jar: subsistema Util de

J2EE-Examples
n WEB-INF/classes/es/.../Messages.properties
n Internacionalización de mensajes
WEB-INF/web.xml (1)
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

<distributable/>

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

<!-- == Standard Action Servlet Configuration (with debugging) == -->

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-
class>
WEB-INF/web.xml (2)
<init-param>
<param-name>application</param-name>
<param-value>es.udc.fbellas.j2ee.strutstutorial.portal3.http.
view.messages.Messages</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/Struts/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
WEB-INF/web.xml (3)
<!-- ================== Servlet mapping ========================== -->

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<!-- ========================= 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-INF/web.xml (y 4)
<!-- ================= Struts Tag Library Descriptors ============ -->

<taglib>
<taglib-uri>/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/Struts/struts-bean.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/Struts/struts-html.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/Struts/struts-logic.tld</taglib-location>
</taglib>

</web-app>
Comentarios (1)
n Servlet org.apache.struts.actions.ActionServlet
n Aparecen dos tags que no hemos usado hasta ahora
n init-param
n Permite definir un parámetro de configuración y su valor
n Accesible vía
Servlet.getServletConfig().getInitParameter()
n load-on-startup
n Indica que el servlet se debería cargar cuando el servidor
arranque la aplicación web
n El valor (opcional) indica el orden relativo de carga con respecto a
otros servlets (cuanto menor sea el valor, antes se carga)
n Parámetros de inicialización
n Véase JavaDoc de org.apache.struts.actions.ActionServlet
n application
n Nombre del fichero de mensajes (sin sufijo .properties)
n Debe estar debajo de WEB-INF/classes y usar un nombre
consistente con su ubicación (como si de una clase se tratase)
Comentarios (2)
n Servlet org.apache.struts.actions.ActionServlet
n Parámetros de inicialización (cont)
n config
n Path de tipo relativo a contexto del fichero de configuración de
Struts
n debug
n Nivel de detalle en los mensajes de depuración que escribe Struts
con el método ServletContext.log
n detail
n Nivel de detalle en los mensajes de depuración que escribe Struts
en System.out
Comentarios (y 3)
n Librerías de tags proporcionadas por Struts
n Aparece un tag que no hemos usado hasta ahora, taglib,
que contiene los elementos
n taglib-uri: URI a usar en la directiva taglib de JSP (para
importar la librería)
n taglib-location: path relativo a contexto del fichero .tld
(Tag Library Descriptor) de la librería de tags
WEB-INF/Struts/struts-config.xml (1)
<?xml version="1.0" encoding="ISO-8859-1" ?>

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

<struts-config>

<!-- ============ Form Bean Definitions =========================== -->

<form-beans>

<form-bean name="loginForm"
type="es.udc.fbellas.j2ee.strutstutorial.portal3.http.view.actionforms.
LoginForm"/>

</form-beans>
WEB-INF/Struts/struts-config.xml (2)
<!-- ============ Global Forward Definitions ====================== -->

<global-forwards>
<forward name="MainPage" path="/MainPage.do" redirect="true"/>
<forward name="InternalError" path="/InternalError.jsp"
redirect="true"/>
</global-forwards>

<!-- ============ Action Mapping Definitions ====================== -->

<action-mappings>

<action path="/MainPage"
type="es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.
actions.MainPageAction">
<forward name="ShowMainPage" path="/MainPage.jsp"/>
</action>

<action path="/Login"
type="es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.
actions.LoginAction"
name="loginForm"
scope="request"
input="/Login.jsp"
validate="true"/>
WEB-INF/Struts/struts-config.xml (y 3)
<action path="/Logout"
type="es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.
actions.LogoutAction"/>

<!-- =================================================================
The standard administrative actions available with Struts. These
must be either omitted or protected by security in a real
application deployment.
================================================================ -->

<action path="/admin/addFormBean"
type="org.apache.struts.actions.AddFormBeanAction"/>

...

<action path="/admin/removeMapping"
type="org.apache.struts.actions.RemoveMappingAction"/>

</action-mappings>

</struts-config>
Comentarios (1)
n Definiciones de nombres lógicos de URLs
n Se usan en la implementación de las acciones para devolver
un ActionForward y en algunas acciones JSP
n Se especifican con forward
n Atributos documentados en JavaDoc de
org.apache.struts.action.ActionForward
n name: Nombre lógico
n path: path relativo a contexto de la URL a la que se invocará
n redirect: true (sendRedirect) o false (forward)
n false por defecto
n Pueden ser globales (global-forwards) o particulares a
una acción (action)
Comentarios (y 2)
n action
n Atributos documentados en JavaDoc de
org.apache.struts.action.ActionMapping
n type: nombre completo de la clase Action
n path: URL (path relativo a contexto) que provocará la
invocación de la acción
n ¡ Se especifican sin el sufijo .do !
n name: nombre del ActionForm (definido por form-bean)
que captura los parámetros de la invocación
n scope: ámbito (request o session) del ActionForm
n En general, request
n input: path relativo a contexto del formulario de entrada
n validate: true si el Front Controller tiene que llamar al
método validate del ActionForm
n En general, true
WEB-INF/classes/es/.../Messages.properties (1)

Buttons.login=Login

ErrorMessages.loginName.notFound=Login name not found


ErrorMessages.mandatoryField=Mandatory field
ErrorMessages.password.incorrect=Incorrect password
ErrorMessages.retry=Please, check if the operation has been performed, \
and retry if necessary

errors.footer=</b></font>
errors.header=<font color="red"><b>

InternalError.title=Internal error
WEB-INF/classes/es/.../Messages.properties (y 2)

Login.loginName=Login name
Login.password=Password
Login.rememberMyPassword=Remember my password (cookies must be enabled)
Login.title=Portal-3 login form

MainPage.hello=Hello
MainPage.login=Login
MainPage.logout=Logout
MainPage.title=Portal-3 main page
MainPage.welcome=Welcome to Portal-3
Comentarios (1)
n Asocia parares <identificadorMensaje, mensaje>
n Convenios de nombrado para los identificadores de mensajes
n Ordenados alfabéticamente
n errors.footer y errors.header son dos identificadores
especiales que entiende la acción html:errors de Struts
n Messages.properties
n Mensajes en el lenguaje por defecto del servidor
n Messages_xx.properties
n Mensajes en el lenguaje cuyo código ISO es xx
n Códigos ISO en
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
n en: Inglés
n es: Español
n gl: Gallego
n Etc.
Comentarios (2)
n Messages.properties sólo resuelve un aspecto
particular de la internacionalización de aplicaciones:
impresión de mensajes en distintos idiomas
n En una aplicación más compleja puede ser necesario tener
trozos de páginas en distintos idiomas (con gran cantidad de
texto estático) y seleccionarlas o incluirlas dinámicamente
desde otras en función del idioma
n Otros aspectos en internacionalización
n Formatear y tratar fechas, horas, números, cantidades
monetarias
n Paquetes java.text y java.util
n Puede requerir tablas para almacenar contenido en distintos
idiomas
n Ej.: un servicio de noticias
es.udc.fbellas.j2ee.strutstutorial.portal3.model.userfacade.delegate

UserFacadeDelegate

+ UserFacadeDelegate()
+ login(loginName : String, password : String, passwordIsEncrypted : boolean) : void

n Simula la facha del modelo que proporciona las


operaciones relativas a la interacción del usuario con
el portal
es.udc.fbellas.j2ee.util.struts.action (1)

Action
(from action)

DefaultAction

+ perform(m : ActionMapping, f : ActionForm, rq : HttpServletRequest, rp : HttpServletResponse) : ActionForward


# doPerform(m : ActionMapping, f : ActionForm, rq : HttpServletRequest, rp : HttpServletResponse) : ActionForward
# doOnInternalError(m : ActionMapping, f : ActionForm, rq : HttpServletRequest, rp : HttpServletResponse) : ActionForward

PropertyValidator
es.udc.fbellas.j2ee.util.struts.action (y 2)
n DefaultAction
n Problema
n En general, las clases Action invocarán una operación sobre
un Business Delegate del modelo o una fachada del
controlador, que puede lanzar InternalErrorException
n Es necesario (1) capturarla, (2) imprimirla en un log (para
depuración) y (3) ir a una página que indique error interno
n Las clases Action derivarán de DefaultAction
n Implementa perform (Template Method) en términos de
doPerform y doOnInternalError
n Las clases hijas implementan doPerform, que tiene la misma
signatura que perform, pero puede lanzar adicionalmente
InternalErrorException
n PropertyValidator
n Clase utilidad para validar campos de entrada comunes
(double, long, String, etc.)
es.udc.fbellas.j2ee.util.struts.action.DefaultAction (1)

package es.udc.fbellas.j2ee.util.struts.action;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;

import es.udc.fbellas.j2ee.util.exceptions.InternalErrorException;
es.udc.fbellas.j2ee.util.struts.action.DefaultAction (2)

public abstract class DefaultAction extends Action {

public ActionForward perform(ActionMapping mapping,


ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

try {
return doPerform(mapping, form, request, response);
} catch (InternalErrorException e) {
return doOnInternalErrorException(mapping, form, request,
response, e);
}

protected abstract ActionForward doPerform(ActionMapping mapping,


ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException, InternalErrorException;
es.udc.fbellas.j2ee.util.struts.action.DefaultAction (y 3)

protected ActionForward doOnInternalErrorException(


ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response,
InternalErrorException internalErrorException)
throws IOException, ServletException {

/*
* Log error, even with debug level <= 0, because it is a
* severe error.
*/
ServletContext servletContext =
servlet.getServletConfig().getServletContext();
servletContext.log(internalErrorException.getMessage(),
internalErrorException);

/* Redirect to input page. */


return mapping.findForward("InternalError");

}
es.udc.fbellas.j2ee.util.struts.action.PropertyValidator (1)

public final class PropertyValidator {

private final static String INCORRECT_VALUE =


"ErrorMessages.incorrectValue";
private final static String MANDATORY_FIELD =
"ErrorMessages.mandatoryField";

public final static long validateLong(ActionErrors errors,


String propertyName, String propertyValue, boolean mandatory,
long lowerValidLimit, long upperValidLimit) {

long propertyValueAsLong = 0;

if (validateMandatory(errors, propertyName, propertyValue,


mandatory)) {

boolean propertyValueIsCorrect = true;


es.udc.fbellas.j2ee.util.struts.action.PropertyValidator (2)

try {
propertyValueAsLong =
new Long(propertyValue).longValue();
if ( (propertyValueAsLong < lowerValidLimit) ||
(propertyValueAsLong > upperValidLimit) ) {
propertyValueIsCorrect = false;
}
} catch (NumberFormatException e) {
propertyValueIsCorrect = false;
}

if (!propertyValueIsCorrect) {
errors.add(propertyName,
new ActionError(INCORRECT_VALUE));
}

return propertyValueAsLong;

}
es.udc.fbellas.j2ee.util.struts.action.PropertyValidator (y 3)

public final static boolean validateMandatory(ActionErrors errors,


String propertyName, String propertyValue) {

if ((propertyValue == null) || (propertyValue.length() == 0)) {


errors.add(propertyName, new ActionError(MANDATORY_FIELD));
return false;
} else {
return true;
}

// Resto de métodos validateXXX => Análogos ...


Comentarios
n org.apache.struts.action.ActionMapping
n Permite acceder a los valores configurados en struts-
config.xml para la acción en ejecución (inclusive a los
forwards globales)
n org.apache.struts.action.ActionErrors
n Juega el papel del mapa de errores que hemos empleado en
apartado anteriores
n El mensaje de error es un
org.apache.struts.action.ActionError, que
dispone de un constructor que permite especificar el
identificador del mensaje de error (en
Messages.properties)
n org.apache.struts.action.ActionForward
n Representa la siguiente URL a la que hay que ir
n El Front Controller lo invocará después de llamar al método
perform sobre la acción
es.udc.fbellas.j2ee.strutstutorial.portal3.http.view.actionforms.LoginForm (1)

public class LoginForm extends ActionForm {

private String loginName;


private String password;
private boolean rememberMyPassword;

public LoginForm() {
reset();
}

public String getLoginName() {


return loginName;
}

public void setLoginName(String loginName) {


this.loginName = loginName.trim();
}
es.udc.fbellas.j2ee.strutstutorial.portal3.http.view.actionforms.LoginForm (2)

public String getPassword() {


return password;
}

public void setPassword(String password) {


this.password = password;
}

public boolean getRememberMyPassword() {


return rememberMyPassword;
}

public void setRememberMyPassword(boolean rememberMyPassword) {


this.rememberMyPassword = rememberMyPassword;
}
es.udc.fbellas.j2ee.strutstutorial.portal3.http.view.actionforms.LoginForm (y 3)

public void reset(ActionMapping mapping, HttpServletRequest request) {


reset();
}

public ActionErrors validate(ActionMapping mapping,


HttpServletRequest request) {

ActionErrors errors = new ActionErrors();

PropertyValidator.validateMandatory(errors, "loginName",loginName);
PropertyValidator.validateMandatory(errors, "password", password);

return errors;

private void reset() {


loginName = null;
password = null;
rememberMyPassword = false;
}

}
Comentarios
n LoginForm
n Juega el mismo papel que la clase vista en el apartado
anterior
n Hereda de org.apache.struts.action.ActionForm
n Generalmente interesa redefinir reset y validate
n reset
n El Front Controller lo llama antes de dar valor a las propiedades
n validate
n Permite validar las propiedades después de que el Front
Controller les haya dado valores
n Sólo se invoca si se ha especificado validate="true" para
la acción correspondiente en struts-config.xml
n Si devuelve un ActionErrors no vacío, el Front Controller (1)
no invocará el método perform sobre la acción
correspondiente, (2) insertará un atributo con los errores en la
request, y (3) hará un forward a la URL que especifica el
atributo input del action correspodiente en struts-
config.xml (formulario de entrada)
es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions

DefaultAction
(from action)

MainPageAction
LoginAction LogoutAction

<<use>>
<<use>> <<use>>

LoginManager

<<use>>

UserFacadeDelegate
(from delegate)
es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions.LoginAction (1)

public class LoginAction extends DefaultAction {

public ActionForward doPerform(ActionMapping mapping,


ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException, InternalErrorException {

/* Get data. */
LoginForm loginForm = (LoginForm) form;
String loginName = loginForm.getLoginName();
String password = loginForm.getPassword();
boolean rememberMyPassword = loginForm.getRememberMyPassword();

/* Do login. */
ActionErrors errors = new ActionErrors();
es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions.LoginAction (y 2)

try {

LoginManager.login(request, response, loginName, password,


rememberMyPassword);

} catch (InstanceNotFoundException e) {
errors.add("loginName", new ActionError(
"ErrorMessages.loginName.notFound"));
} catch (IncorrectPasswordException e) {
errors.add("password", new ActionError(
"ErrorMessages.password.incorrect"));
}

/* Return ActionForward. */
if (errors.empty()) {
return mapping.findForward("MainPage");
} else {
saveErrors(request, errors);
return new ActionForward(mapping.getInput());
}

}
es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions.LogoutAction

public class LogoutAction extends DefaultAction {

public ActionForward doPerform(ActionMapping mapping,


ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException, InternalErrorException {

/* Do logout. */
LoginManager.logout(request, response);

/* Return ActionForward. */
return mapping.findForward("MainPage");

}
Comentarios
n Las acciones utilizan el método saveErrors
(heredado de org.struts.apache.action.Action)
para insertar un atributo con los errores en la
request
MainPage.jsp (1)
<%@ taglib uri="/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/struts-html.tld" prefix="html" %>
<%@ taglib uri="/struts-logic.tld" prefix="logic" %>

<html>
<head>
<title><bean:message key="MainPage.title"/></title>
</head>

<body text="#000000" bgcolor="#ffffff" link="#000ee0" vlink="#551a8b"


alink="#000ee0">
MainPage.jsp (2)
<%-- Welcome --%>

<h1>

<logic:notPresent name="loginName" scope="session">


<bean:message key="MainPage.welcome"/>
</logic:notPresent>

<logic:present name="loginName" scope="session">


<bean:message key="MainPage.hello"/>
<bean:write name="loginName" scope="session"/>
</logic:present>

</h1>

<%-- Some <br>'s --%>

<br>
<br>
<br>
MainPage.jsp (y 3)
<%-- Links to Login or Logout --%>

<logic:notPresent name="loginName" scope="session">


<html:link href="Login.jsp">
<bean:message key="MainPage.login"/>
</html:link>
</logic:notPresent>

<logic:present name="loginName" scope="session">


<html:link href="Logout.do">
<bean:message key="MainPage.logout"/>
</html:link>
</logic:present>

</body>

</html>
Login.jsp (1)
<%@ taglib uri="/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/struts-html.tld" prefix="html" %>

<html>
<head>
<title><bean:message key="Login.title"/></title>
</head>

<body text="#000000" bgcolor="#ffffff">

<html:form action="Login.do">

<table width="100%" border="0" align="center" cellspacing="12">

<%-- Login name --%>

<tr>
<th align="right" width="50%">
<bean:message key="Login.loginName"/>
</th>
<td align="left">
<html:text property="loginName" size="16" maxlength="16"/>
<html:errors property="loginName"/>
</td>
</tr>
Login.jsp (2)
<%-- Password --%>

<tr>
<th align="right" width="50%">
<bean:message key="Login.password"/>
</th>
<td align="left">
<html:password property="password" size="16"
maxlength="16"/>
<html:errors property="password"/>
</td>
</tr>

<%-- Remember my password --%>

<tr>
<th align="right" width="50%">
<bean:message key="Login.rememberMyPassword"/>
</th>
<td align="left">
<html:checkbox property="rememberMyPassword"/>
</td>
</tr>
Login.jsp (y 3)
<%-- Login button --%>

<tr>
<td width="50%"></td>
<td align="left" width="50%">
<html:submit>
<bean:message key="Buttons.login"/>
</html:submit>
</td>
</tr>

</table>

</html:form>

</body>

</html>
Comentarios
n html:text, html:password y html:checkbox
recuperan el valor de la propiedad asociada a través
del método getXXX (property="XXX") sobre la
instancia de LoginForm enganchada a la request
n Saben que el ActionForm asociado es de tipo LoginForm
dado que el atributo action de html:form es igual a
Login.do
n struts-config.xml especifica LoginForm como la clase
ActionForm para la URL /Login.do
n html:errors
n Imprime el mensaje de error asociado a la propiedad
especificada si figura en el ActionErrors enganchado a la
request
n El mensaje vendrá flanqueado por errors.header y
errors.footer (Messages.properties)
InternalError.jsp
<%@ taglib uri="/struts-bean.tld" prefix="bean" %>

<html>
<head>
<title><bean:message key="InternalError.title"/></title>
</head>

<body text="#000000" bgcolor="#ffffff">

<h3><div align="center"><font color="red">


<bean:message key="InternalError.title"/>.
<bean:message key="ErrorMessages.retry"/>
</font></div></h3>

</body>

</html>
Un pequeño problema
n Situación
n Imaginemos que la página de bienvenida fuese
MainPage.jsp
n En realidad es Index.jsp
n Un usuario hace el login y selecciona “Remember my
password”
n Termina la sesión
n Accede dos días después tecleando la URL de la aplicación
en su navegador (ej.: http://www.acme.org/MiniPortal)
n La sesión no contendrá el atributo loginName, dado que no
se ha ejecutado LoginManager.getLoginName
n Se le redirige a la página de login
Un solución
n El navegador nunca invocará a /MainPage.jsp
directamente, sino a /Index.jsp o /MainPage.do
n Index.jsp
n Página de bienvenida
n Hace un forward a /MainPage.do => se ejecuta
MainPageAction
n MainPageAction
n LoginManager.getLoginName y forward a
/MainPage.jsp
n Cuando se haga un sendRedirect a la página principal se
hará siempre con la URL /MainPage.do y nunca con
/MainPage.jsp
n /MainPage.jsp nunca aparecerá en la caja de diálogo del
navegador, de manera que el usuario nunca hará un bookmark
a esa página, sino a /MainPage.do o /Index.jsp
n En MiniPortal volveremos a discutir este problema
es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions.MainPageAction

public class MainPageAction extends DefaultAction {

public ActionForward doPerform(ActionMapping mapping,


ActionForm form, HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException, InternalErrorException {

/*
* "LoginManager.getLoginName" creates an appropriate session
* if the session had expired, or the user had not logged in,
* but he/she had selected "remember my password" in the last
* login.
*/
LoginManager.getLoginName(request);

/* Return ActionForward. */
return mapping.findForward("ShowMainPage");

}
Index.jsp
<jsp:forward page="MainPage.do"/>

También podría gustarte