2. Introducción (I)
Actions clases más flexibles
Responsabilidades:
Acceder a capa de negocio
Preparar los objetos de datos para capa de presentación
Tratamiento de errores
¿Dónde encaja un Action ?
ActionForward proporciona un enlace a página de entrada
ActionForm captura la entrada
ActionMapping configura el Action
Action envía la entrada a la base de datos
3. Introducción (II)
¿Qué son?
Son miniservlets.
El servlet ActionServlet “reparte el juego” entre los
actions
Se fija en los ActionMapping para enviar a uno u otro
Todo Action devuelve un ActionForward
El ActionServlet hace la redirección a la página adecuada
Multihilo Sólo se instancia una clase Action de
cada tipo por aplicación
Punto de entrada de ejecución
Método perform() (Struts 1.0) ó método execute()
(desde 1.1)
4. Introducción (III)
¿Qué parámetros aceptan?
mapping ActionMapping utilizado para
invocar este Action
form ActionForm especificado (si lo hay) en
el ActionMapping
request El contexto del request (mismo que
en Servlet)
Response Contexto del response (mismo que
en Servlet)
5. Introducción (IV)
¿Qué funciones tienen?
Validar precondiciones
Validaciones no realizadas en ActionForm. P.e.: ¿Está
usuario logeado?
Llamar a los métodos de lógica de negocio
Buena práctica separar de Action lógica de negocio
Tratamiento de errores
Registrar errores. Objetos ActionErrors, ActionError y
método saveErrors
Mostrar mensaje de error “localizado”
Rutar el control a la vista adecuada
return mapping.findForward("continue");
6. Flujo de control (I)
Struts-config.xml
jsp JSP
io.
lar
mu
for
e st
qu
Re
Envía form a hazAlgo.do
Elige execute() Action Elige
ActionServlet Action JSP
HazAlgo
ActionForm
Form HTML
devue
lve resulta
do
JSP
7. Flujo de control (II)
Usuario solicita un formulario HTML
Formulario le envía a hazAlgo.do
Struts-config.xml mapea /hazAlgo.do a HazAlgoAction (derivada de
Action)
Se invoca método execute() de HazAlgoAction
Como argumento va ActionForm con datos del formulario
El objeto Action HazAlgoAction invoca lógica de negocio y/o accede
al modelo (BBDD)
Action utiliza método mapping.findForward para buscar recurso
(definido en struts-config.xml) a dónde redireccionar (JSP, otro
Action, página HTML, etc.)
Struts redirecciona a salida adecuada
Si es JSP se pueden usar tags de struts <bean:message> para
internacionalizar salida y <bean:write> para escribir variables
8. Escribiendo una aplicación (I)
Modificar struts-config.xml:
Relacionar paths XXXX.do a clases Action
Especificar condiciones de retorno a
páginas JSP
Declarar todos los form beans utilizados
(ActionForm)
Definir un ActionForm
Clase derivada de ActionForm que contiene
datos de un formulario HTML
9. Escribiendo una aplicación (II)
Crear JavaBeans de resultados:
Contendrán los resultados de la capa de negocio
y/o del modelo
Definir una clase Action que reciba las
peticiones:
struts-config.xml determina:
Entrada: puede haber varias URIs mapeadas a un mismo
Action
Salida: a qué JSP se devolverá el control dependiendo de
estado: éxito, error en BBDD, error autenticación, etc.
10. Escribiendo una aplicación (III)
Crear el formulario que invoca a hazAlgo.do:
El atributo action de formulario HTML apunta a hazAlgo.do
Pueden usarse Tags de Struts para facitar tarea <html:form>
Mostrar resultados en JSP
Se utilizan tags de Struts <bean:write> para copiar valores de
JavaBean de resultados en página
Alternativamente puede usarse JSLT
Si la página JSP sólo es accesible desde Action pueden ir
dentro de WEB-INF
Si JSP tiene sentido como página accesible directamente
puede hacerse redirect (petición pasa por cliente) en vez de
forward (petición no pasa por cliente):
<forward ... redirect="true"/> (en struts-
config.xml)
11. Ejemplo 1: Mapear resultados
Aplicación básica de registro
Familiarización con Actions
No se comprobará entrada
Mapeo de datos
Localización
http://localhost:8080/struts-actions
Clase Action
RegisterAction1
Dentro de paquete app
Siempre devuelve página de éxito.
Creamos proyecto en NetBeans “struts-actions”
partiendo de fuentes de directorio “struts-actions”
12. Ejemplo 1:struts-config.xml (I)
Creamos entrada para register1.do
Creamos entrada <action> dentro de <action-mappings>
Notas sobre atributos de action:
Path:
Es el path que se quiere maper al action
Es relativo al contexto de la aplicación.
NO incluye el .do
Path=“/register1” http://localhost:8080/struts-actions/register1.do
Type: Es la clase Action a la que se mapea URI
<action-mappings>
<action path="/register1"
type=“app.RegisterAction1“
</action>
</action-mappings>
13. Ejemplo 1:struts-config.xml (II)
Especificamos página de retorno
Creamos entrada <forward> con nombre “success”
Dos alternativas
Página “privada” para un action concreto
Se define anidado dentro de la etiqueta <action> correspondiente
Página accesible desde más de un action o recurso.
Se define dentro de <global-forwards> fuera de <action-mappings>
Definimos la página de retorno como “global”:
Dentro de directorio WEB-INF No será accesible desde el navegador
directamente
<global-forwards>
<forward name=“success“
path=“/WEB-INF/results/confirm.jsp">
</forward>
</global-forwards>
14. Ejemplo 1:Creamos Action
Todas deben derivar de Action
Deben ir todas en el mismo paquete
El método principal a redefinir es execute().
Está relacionado con nuestra lógica de negocio
No requiere declaraciones en struts-config.xml
Siempre debería acabar con mapping.findForward
Puede haber diferentes retornos dependiendo del éxito de la acción
La elección del JSP específico de acuerdo con el estado de salida se definía en struts-config.xml (podemos cambiar JSPs sin
tener que recompilar)
Por ahora no usaremos SuggestionBean
package app;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class RegisterAction1 extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
return(mapping.findForward("success"));
}
}
15. Ejemplo 1:Presentación
Tenemos lógica básica
Falta parte de presentación
Formulario que apunte a register1.do
Página de entrada: register1.jsp:
<HTML>
<HEAD><TITLE></TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Registro de nueva cuenta</H1>
<FORM ACTION="register1.do" METHOD="POST">
Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR>
Password: <INPUT TYPE="PASSWORD" NAME="password"><BR>
<INPUT TYPE="SUBMIT" VALUE="Registrar">
</FORM>
</CENTER>
</BODY></HTML>
16. Ejemplo 1:Presentación (II)
Página de resultado
Se realiza forward dentro del servidor
No interesa que sea accesible directamente
La creamos dentro de WEB-INF
Página WEB-INF/results/confirm.jsp que sólo muestra mensaje de éxito
<HTML>
<HEAD><TITLE></TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Ha registrado la cuenta con éxito</H1>
Felicidades.
</CENTER>
</BODY></HTML>
17. Ejemplo 1:Resultados
Página de inicio:
http://localhost:8080/struts-actions/register1.jsp
19. Ejemplo 2: Múltiples
resultados
Extensión de aplicación de ejemplo 1
Mapear más de un resultado según condición de
error
Nueva clase Action:
RegisterAction2
Devolverá “success”, “bad-address” o “bad-password”
Nuevas páginas de resultados
WEB-INF/result/bad-address.jsp
WEB-INF/result/bad-password.jsp
20. Ejemplo 2: Entrada
Reaprovechamos register1.jsp para
register2.jsp
Cambiamos ACTION del formulario que apunte a:
register2.do
<HTML>
<HEAD><TITLE>New Account Registration</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Registro de nueva cuenta (2ª forma)</H1>
<FORM ACTION="register2.do" METHOD="POST">
Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR>
Password: <INPUT TYPE="PASSWORD" NAME="password"><BR>
<INPUT TYPE="SUBMIT" VALUE="Registrar">
</FORM>
</CENTER>
</BODY></HTML>
21. Ejemplo 2: struts-config.xml
Añadimos nuevo action (register2.do)
Tiene varias salidas dependiendo del
resultado de la operación
<action-mappings>
<action path="/register2"
type="coreservlets.RegisterAction2">
<forward name="bad-address"
path="/WEB-INF/results/bad-address.jsp"/>
<forward name="bad-password"
path="/WEB-INF/results/bad-password.jsp"/>
<forward name="success"
path="/WEB-INF/results/confirm.jsp"/>
</action>
</action-mappings>
22. Ejemplo 2:Creamos Action
Ahora nuestro Action tiene algo de lógica
Chequea formato de dirección email
Chequea longitud mínima del password
public class RegisterAction2 extends Action {
public ActionForward
execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
String email = request.getParameter("email");
String password = request.getParameter("password");
if ((email == null) || (email.trim().length() < 3) || (email.indexOf("@") == -1)) {
return(mapping.findForward("bad-address"));
} else if ((password == null) || (password.trim().length() < 6)) {
return(mapping.findForward("bad-password"));
} else {
return(mapping.findForward("success"));
}
}
}
23. Ejemplo 2:Presentación
Páginas de salida de error que muestren mensajes adecuados:
WEB-INF/result/bad-address.jsp
WEB-INF/result/bad-password.jsp
<HTML>
<HTML>
<HEAD><TITLE></TITLE></HEAD>
<HEAD><TITLE></TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<CENTER>
<H1>Password incorrecto</H1>
<H1>Dirección de email incorrecta</H1>
El password debe tener al menos 6 caracteres.
Debe tener formato username@host.
Por favor inténtelo <A HREF="register2.jsp">
Por favor <A HREF="register2.jsp">
de nuevo</A>.
Intentelo de nuevo</A>.
</CENTER>
</CENTER>
</BODY></HTML>
</BODY></HTML>
Bad-address.jsp Bad-password.jsp
24. Ejemplo 2:Resultados
Accedemos a: http://localhost:8080/struts-actions/register2.jsp
Páginas de error en caso de introducir mal email o password menor de 6
caracteres
25. Ejemplo 3: Con form beans
Partimos de Ejemplo2
Añadimos sugerencias para el usuario en caso de que no complete
algún campo
Utilizaremos un form bean
Contiene los datos que recibimos del formulario
Familiarización de uso de ActionForms
Utilizaremos un bean de resultados
Representa resultados del modelo o lógica de negocio
Haremos uso de tags para JSP de struts
<bean:write> nos facilitará el manejo de campos de los beans
Para poder utilizar los tags <bean:xxxxx> ha de incluirs en el JSP:
<%@ taglib uri=http://struts.apache.org/tags-bean prefix="bean" %>
26. Ejemplo 3:struts-config.xml (I)
Definimos el form bean a utilizar:
Creamos entrada <form-bean> con nombre
“userFormBean”
Parámetros
Name: nombre simbólico que se referenciará en actions
Type: clase que implementa el ActionForm
<form-beans>
<form-bean name=“userFormBean“
type=“app.UserFormBean">
</form-bean>
</form-beans>
27. Ejemplo 3:struts-config.xml (II)
Definimos un nuevo action (register3.do) con dos
nuevos argumentos
Name: nombre simbólico que hace referencia al form-bean
definido (ActionForm)
Scope: Ámbito donde es válido el form-bean. Por defecto es
session. Ponemos request (se inicialicen los datos con cada
envío).
<action path="/register3"
type=“app.RegisterAction3"
name="userFormBean"
scope="request“>
<forward name="bad-address"
path="/WEB-INF/results/bad-address-tags.jsp"/>
<forward name="bad-password"
path="/WEB-INF/results/bad-password-tags.jsp"/>
<forward name="success"
path="/WEB-INF/results/confirm.jsp"/>
</action>
28. Ejemplo 3:Creamos form bean
Definimos un form bean básico
Clase derivada de ActionForm
Debe tener parámetros mutables que se correspondan con campos
del formulario HTML
Debe tener parámetros leibles para cada uno que quiera mostrarse
en el JSP de salida
package app;
import org.apache.struts.action.*;
public class UserFormBean extends ActionForm {
private String email = "";
private String password = "";
public String getEmail() { return(email); }
public void setEmail(String email) {
this.email = email;
}
public String getPassword() { return(password); }
public void setPassword(String password) {
this.password = password;
}
}
29. Ejemplo 3:Creamos bean de
resultados
Definimos el bean de resultados
Está relacionado con nuestra lógica de negocio
No requiere declaraciones en struts-config.xml
package app;
import org.apache.struts.action.*;
public class SuggestionBean {
private String email = "";
private String password = "";
public SuggestionBean(String email, String password){
this.email = email;
this.password = password;
}
public String getEmail() { return this.email; }
public String getPassword() { return this.password; }
}
30. Ejemplo 3:Creamos “lógica de
negocio”
Definimos una clase que implemente nuestra lógica de
negocio
Podría hacer cualquier cosa
Clase de ayuda que nos sugiera combinaciones
usuario/password
package app;
public class SuggestionUtils {
private static String[] suggestedAddresses =
{ “emiliobotin@bsch.es",
"gates@microsoft.com",
“ortega@inditex.com",
"ellison@oracle.com" };
private static String chars =
"abcdefghijklmnopqrstuvwxyz0123456789#@$%^&*?!";
public static SuggestionBean getSuggestionBean() {
String address = randomString(suggestedAddresses);
String password = randomString(chars, 8);
return(new SuggestionBean(address, password));
}
/* … Mirar código ejemplo para randomString() … */
}
31. Ejemplo 3:Creamos action
Partimos del Action del ejemplo anterior
Ahora recuperamos los datos de entrada del ActionForm (en vez del request)
Metemos bean SuggestionBean como atributo del objeto request como
resultado en las páginas de error.
public class RegisterAction2 extends Action {
public ActionForward
execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
UserFormBean userBean = (UserFormBean) form;
String email = userBean.getEmail();
String password = userBean.getPassword();
if ((email == null) || (email.trim().length() < 3) || (email.indexOf("@") == -1)) {
request.setAttribute("suggestionBean",
SuggestionUtils.getSuggestionBean());
return(mapping.findForward("bad-address"));
} else if ((password == null) || (password.trim().length() < 6)) {
request.setAttribute("suggestionBean",
SuggestionUtils.getSuggestionBean());
return(mapping.findForward("bad-password"));
} else {
return(mapping.findForward("success"));
}
}
}
32. Ejemplo 3:Presentación
El punto de entrada: register3.jsp
Igual sólo que apunta a register3.do
<HTML>
<HEAD><TITLE>New Account Registration</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Registro de nueva cuenta (con sugerencias)</H1>
<FORM ACTION="register3.do" METHOD="POST">
Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR>
Password: <INPUT TYPE="PASSWORD" NAME="password"><BR>
<INPUT TYPE="SUBMIT" VALUE="Registrar">
</FORM>
</CENTER>
</BODY></HTML>
33. Ejemplo 3:Presentación (II)
Salida
Hacemos uso de tag <bean:write>. Por defecto filtra caracteres malignos y los convierte a código
HTML. Podemos evitar el filtrado con argumento: filter=“false”
“>” “>
Para hacer uso de los tags <bean:XXXX> hay que importar:
<%@ taglib uri="http://struts.apache.org/tags-bean"
prefix="bean" %>
Podemos referencias los beans (tanto los normales como ActionForms) por su nombre (especificado en
sruts-config.xml)
Creamos WEB-INF/results/bad-address-tags.jsp
<HTML>
<HEAD><TITLE>New Account Registration</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Registro de nueva cuenta (con sugerencias)</H1>
<FORM ACTION="register3.do" METHOD="POST">
Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR>
Password: <INPUT TYPE="PASSWORD" NAME="password"><BR>
<INPUT TYPE="SUBMIT" VALUE="Registrar">
</FORM>
</CENTER>
</BODY></HTML>
34. Ejemplo 3:Presentación (III)
Salida
Hacemos uso de tag <bean:write>. Por defecto filtra caracteres malignos y los convierte a código
HTML. Podemos evitar el filtrado con argumento: filter=“false”
“>” “>
Para hacer uso de los tags <bean:XXXX> hay que importar:
<%@ taglib uri="http://struts.apache.org/tags-bean"
prefix="bean" %>
Podemos referencias los beans (tanto los normales como ActionForms) por su nombre (especificado en
sruts-config.xml)
Creamos WEB-INF/results/bad-address-tags.jsp
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Illegal Email Address</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Email incorrecto</H1>
La dirección "<bean:write name="userFormBean" property="email"/>"
debe tener el formato usuario@host (p.e. "<bean:write name="suggestionBean" property="email"/>")
<p>Inténtelo <A HREF="register3.jsp">de nuevo</A>.</p>
</CENTER>
</BODY></HTML>
35. Ejemplo 3:Presentación (IV)
Salida
Y lo mismo para WEB-INF/results/bad-
address-tags.jsp
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Illegal Password</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<CENTER>
<H1>Password Incorrecto</H1>
El password "<bean:write name="userFormBean" property="password"/>" es muy corto.
Debe tener al menos 6 caracteres. P.e.: "<bean:write name="suggestionBean" property="password"/>"
Por favor inténtelo <A HREF="register3.jsp">de nuevo</A>.
</CENTER>
</BODY></HTML>
36. Ejemplo 3:Resultados
Si introducimos mal dirección o password nos
recordará lo introducido y nos dará sugerencias