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 segn el patrn
arquitectnico Model-View-Controller
Subproyecto de Jakarta
n

n
n

Autor principal: Craig R. McClanahan

Funciona sobre cualquier servidor de aplicaciones


web que implemente las APIs de servlets y JSP
Julio 2001: versin 1.0
Ha ganado gran relevancia en el mundo de las
aplicaciones web Java
Paquetizado en un fichero .jar

Qu proporciona Struts ?
n
n

Un servlet Front Controller y clases relacionadas


Un gran nmero de acciones JSP
n
n

View Helpers
La mayor parte de las que se necesitan en una situacin real

Un pool genrico de conexiones a una BD relacional


n

Implementa javax.sql.DataSource

El patrn Front Controller en Struts (1)


javax.servlet.http.HttpServlet

org.apache.struts.action.ActionServlet
0..n

# doGet
# doPost
<<use>>

org.apache.struts.action.Action
+ perform

<<instantiate>>

org.apache.struts.action.ActionForm
+ reset
+ validate

Action1

ActionN

...

ActionForm1

ActionFormN

...

<<use>>

El patrn Front Controller en Struts (2)


n

ActionServlet
n
n

Servlet Front Controller


En web.xml se especifica que todas las URLs que impliquen
procesamiento (por GET o POST) vayan a este servlet
n

Clases ActionForm
n

Si el programador lo desea, puede acceder a los parmetros de la


request a travs de un JavaBean que extiende ActionForm
n

Ej.: las URLs que termine en .do

Especialmente til en formularios

Clase Action => mtodo perform


n

Accede a los parmetros de la request, directamente o va el


ActionForm correspondiente
Realiza la operacin invocando un mtodo de un Session
Facade del modelo o una fachada del controlador
Deja el resultado devuelto por el mtodo en la request o en la
sesin
Devuelve un objeto ActionForward, que representa la URL que
hay que visualizar a continuacin (sendRedirect o forward)

El patrn Front Controller en Struts (3)


n

Fichero de configuracin
n

Clases ActionForm que usa nuestra aplicacin


n
n

Nombre lgico (ej.: loginForm)


Nombre completo de la clase (ej.:
es.udc.fbellas.j2ee.strutstutorial.portal3.http
.view.actionforms.LoginForm)

URLs que implican procesamiento


n

URL de tipo path relativo a contexto (ej.: /Login)


n

No llevan el .do final

Nombre completo de la clase Action (ej.:


es.udc.fbellas.j2ee.strutstutorial.portal3.http
.controller.actions.LoginAction)
Nombre lgico de la clase ActionForm asociada

El patrn Front Controller en Struts (y 4)


n

Fichero de configuracin (cont)


n

Definiciones de nombres lgicos de URLs


n

n
n

Nombre que usan las acciones cuando devuelven un


ActionForward (ej.: ShowMainPage)
sendRedirect o forward
URL a invocar (ej.: /MainPage.jsp)

Cuando el servlet ActionServlet arranca (init), lee el


fichero de configuracin
Crea una nica instancia de cada clase Action
n

n
n

No se crea una instancia de una clase Action por cada


peticin que se recibe
Tienen que ser thread-safe
Misma situacin que cuando se trabaja con servlets

Acciones JSP
n

Bean
n

Imprimir el valor de las propiedades de JavaBeans de


manera segura
Soporte para internacionalizacin de mensajes

HTML
n

Generacin de HTML bsico


n
n

Logic
n
n

Campos de entrada en formularios


Enlaces (con URL rewriting)

Si mayor que, si menor que, etc.


Iteracin sobre colecciones de objetos

Template
n
n

Caso particular del patrn Composite View


Lo veremos con MiniBank y MiniPortal

Arquitectura MVC con Struts


n

Modelo
n

Controlador
n
n
n

Clases independientes de la vista y el controlador


Quizs se necesite extender el servlet ActionServlet
Conjunto de clases Action
Interactan con el modelo y seleccionan la siguiente vista
(dejndole los datos en uno de los cuatro posibles mbitos,
normalmente request o session)

Vista
n
n

Conjunto de clases ActionForm


Conjunto de pginas JSP
n
n
n

No contienen cdigo Java


Slo visualizan datos
Usan acciones JSP (las de Struts, las estndares y quizs
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 das ms 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 libreras de las acciones


proporcionadas por Struts
struts-config.xml: configuracin de Struts para la
aplicacin del tutorial

WEB-INF/lib

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
WEB-INF/classes/es/.../Messages.properties
n

Internacionalizacin 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</servletclass>

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
n

load-on-startup
n

Permite definir un parmetro de configuracin y su valor


Accesible va
Servlet.getServletConfig().getInitParameter()
Indica que el servlet se debera cargar cuando el servidor
arranque la aplicacin web
El valor (opcional) indica el orden relativo de carga con respecto a
otros servlets (cuanto menor sea el valor, antes se carga)

Parmetros de inicializacin
n
n

Vase JavaDoc de org.apache.struts.actions.ActionServlet


application
n
n

Nombre del fichero de mensajes (sin sufijo .properties)


Debe estar debajo de WEB-INF/classes y usar un nombre
consistente con su ubicacin (como si de una clase se tratase)

Comentarios (2)
n

Servlet org.apache.struts.actions.ActionServlet
n

Parmetros de inicializacin (cont)


n

config
n

debug
n

Path de tipo relativo a contexto del fichero de configuracin de


Struts
Nivel de detalle en los mensajes de depuracin que escribe Struts
con el mtodo ServletContext.log

detail
n

Nivel de detalle en los mensajes de depuracin que escribe Struts


en System.out

Comentarios (y 3)
n

Libreras 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 librera)
taglib-location: path relativo a contexto del fichero .tld
(Tag Library Descriptor) de la librera 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 lgicos de URLs


n

Se usan en la implementacin de las acciones para devolver


un ActionForward y en algunas acciones JSP
Se especifican con forward
n

n
n
n

Atributos documentados en JavaDoc de


org.apache.struts.action.ActionForward
name: Nombre lgico
path: path relativo a contexto de la URL a la que se invocar
redirect: true (sendRedirect) o false (forward)
n

false por defecto

Pueden ser globales (global-forwards) o particulares a


una accin (action)

Comentarios (y 2)
n

action
n

n
n

Atributos documentados en JavaDoc de


org.apache.struts.action.ActionMapping
type: nombre completo de la clase Action
path: URL (path relativo a contexto) que provocar la
invocacin de la accin
n

name: nombre del ActionForm (definido por form-bean)


que captura los parmetros de la invocacin
scope: mbito (request o session) del ActionForm
n

n
n

Se especifican sin el sufijo .do !

En general, request

input: path relativo a contexto del formulario de entrada


validate: true si el Front Controller tiene que llamar al
mtodo 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
n
n

Messages.properties
n

Convenios de nombrado para los identificadores de mensajes


Ordenados alfabticamente
errors.footer y errors.header son dos identificadores
especiales que entiende la accin html:errors de Struts
Mensajes en el lenguaje por defecto del servidor

Messages_xx.properties
n
n

Mensajes en el lenguaje cuyo cdigo ISO es xx


Cdigos ISO en
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt

en: Ingls
es: Espaol
gl: Gallego

Etc.

n
n

Comentarios (2)
n

Messages.properties slo resuelve un aspecto


particular de la internacionalizacin de aplicaciones:
impresin de mensajes en distintos idiomas
n

En una aplicacin ms compleja puede ser necesario tener


trozos de pginas en distintos idiomas (con gran cantidad de
texto esttico) y seleccionarlas o incluirlas dinmicamente
desde otras en funcin del idioma

Otros aspectos en internacionalizacin


n

Formatear y tratar fechas, horas, nmeros, cantidades


monetarias
n

Paquetes java.text y java.util

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

Simula la facha del modelo que proporciona las


operaciones relativas a la interaccin 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

Es necesario (1) capturarla, (2) imprimirla en un log (para


depuracin) y (3) ir a una pgina que indique error interno

Las clases Action derivarn de DefaultAction


n

En general, las clases Action invocarn una operacin sobre


un Business Delegate del modelo o una fachada del
controlador, que puede lanzar InternalErrorException

Implementa perform (Template Method) en trminos de


doPerform y doOnInternalError
Las clases hijas implementan doPerform, que tiene la misma
signatura que perform, pero puede lanzar adicionalmente
InternalErrorException

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
import
import
import
import
import
import
import
import
import
import

java.io.IOException;
javax.servlet.ServletContext;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.ServletException;
org.apache.struts.action.Action;
org.apache.struts.action.ActionMapping;
org.apache.struts.action.ActionForm;
org.apache.struts.action.ActionForward;
org.apache.struts.action.ActionError;
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 mtodos validateXXX => Anlogos ...

Comentarios
n

org.apache.struts.action.ActionMapping
n

org.apache.struts.action.ActionErrors
n

Permite acceder a los valores configurados en strutsconfig.xml para la accin en ejecucin (inclusive a los
forwards globales)
Juega el papel del mapa de errores que hemos empleado en
apartado anteriores
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)

org.apache.struts.action.ActionForward
n
n

Representa la siguiente URL a la que hay que ir


El Front Controller lo invocar despus de llamar al mtodo
perform sobre la accin

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
Hereda de org.apache.struts.action.ActionForm

Generalmente interesa redefinir reset y validate


n

reset
n

El Front Controller lo llama antes de dar valor a las propiedades

validate
n

Permite validar las propiedades despus de que el Front


Controller les haya dado valores
Slo se invoca si se ha especificado validate="true" para
la accin correspondiente en struts-config.xml
Si devuelve un ActionErrors no vaco, el Front Controller (1)
no invocar el mtodo perform sobre la accin
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 strutsconfig.xml (formulario de entrada)

es.udc.fbellas.j2ee.strutstutorial.portal3.http.controller.actions
DefaultAction
(from action)

MainPageAction

<<use>>

LoginAction

<<use>>

LogoutAction

<<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 mtodo 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 travs
del mtodo 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
struts-config.xml especifica LoginForm como la clase
ActionForm para la URL /Login.do

html:errors
n

Imprime el mensaje de error asociado a la propiedad


especificada si figura en el ActionErrors enganchado a la
request
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 pequeo problema
n

Situacin
n

Imaginemos que la pgina de bienvenida fuese


MainPage.jsp
n

n
n

En realidad es Index.jsp

Un usuario hace el login y selecciona Remember my


password
Termina la sesin
Accede dos das despus tecleando la URL de la aplicacin
en su navegador (ej.: http://www.acme.org/MiniPortal)
La sesin no contendr el atributo loginName, dado que no
se ha ejecutado LoginManager.getLoginName
Se le redirige a la pgina de login

Un solucin
n

El navegador nunca invocar a /MainPage.jsp


directamente, sino a /Index.jsp o /MainPage.do
n

Index.jsp
n
n

MainPageAction
n

LoginManager.getLoginName y forward a
/MainPage.jsp

Cuando se haga un sendRedirect a la pgina principal se


har siempre con la URL /MainPage.do y nunca con
/MainPage.jsp
n

Pgina de bienvenida
Hace un forward a /MainPage.do => se ejecuta
MainPageAction

/MainPage.jsp nunca aparecer en la caja de dilogo del


navegador, de manera que el usuario nunca har un bookmark
a esa pgina, sino a /MainPage.do o /Index.jsp

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